bfe81d3c228a284c26cb84dc86bea117f35dc275
[WebKit.git] / Source / WebCore / testing / Internals.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  * Copyright (C) 2013-2020 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 "ActivityState.h"
32 #include "AnimationTimeline.h"
33 #include "ApplicationCacheStorage.h"
34 #include "AudioSession.h"
35 #include "AudioTrackPrivateMediaStream.h"
36 #include "Autofill.h"
37 #include "BackForwardCache.h"
38 #include "BackForwardController.h"
39 #include "BitmapImage.h"
40 #include "CSSAnimationController.h"
41 #include "CSSKeyframesRule.h"
42 #include "CSSMediaRule.h"
43 #include "CSSPropertyParser.h"
44 #include "CSSStyleRule.h"
45 #include "CSSSupportsRule.h"
46 #include "CacheStorageConnection.h"
47 #include "CacheStorageProvider.h"
48 #include "CachedImage.h"
49 #include "CachedResourceLoader.h"
50 #include "CertificateInfo.h"
51 #include "Chrome.h"
52 #include "ChromeClient.h"
53 #include "ClientOrigin.h"
54 #include "ComposedTreeIterator.h"
55 #include "CookieJar.h"
56 #include "Cursor.h"
57 #include "CustomHeaderFields.h"
58 #include "DOMRect.h"
59 #include "DOMRectList.h"
60 #include "DOMStringList.h"
61 #include "DOMURL.h"
62 #include "DOMWindow.h"
63 #include "DeprecatedGlobalSettings.h"
64 #include "DiagnosticLoggingClient.h"
65 #include "DisabledAdaptations.h"
66 #include "DisplayList.h"
67 #include "Document.h"
68 #include "DocumentLoader.h"
69 #include "DocumentMarkerController.h"
70 #include "DocumentTimeline.h"
71 #include "Editor.h"
72 #include "Element.h"
73 #include "EventHandler.h"
74 #include "EventListener.h"
75 #include "EventLoop.h"
76 #include "EventNames.h"
77 #include "ExtendableEvent.h"
78 #include "ExtensionStyleSheets.h"
79 #include "FetchResponse.h"
80 #include "File.h"
81 #include "FontCache.h"
82 #include "FormController.h"
83 #include "Frame.h"
84 #include "FrameLoader.h"
85 #include "FrameView.h"
86 #include "FullscreenManager.h"
87 #include "GCObservation.h"
88 #include "GridPosition.h"
89 #include "HEVCUtilities.h"
90 #include "HTMLAnchorElement.h"
91 #include "HTMLCanvasElement.h"
92 #include "HTMLIFrameElement.h"
93 #include "HTMLImageElement.h"
94 #include "HTMLInputElement.h"
95 #include "HTMLLinkElement.h"
96 #include "HTMLNames.h"
97 #include "HTMLPictureElement.h"
98 #include "HTMLPlugInElement.h"
99 #include "HTMLPreloadScanner.h"
100 #include "HTMLSelectElement.h"
101 #include "HTMLTextAreaElement.h"
102 #include "HTMLVideoElement.h"
103 #include "HistoryController.h"
104 #include "HistoryItem.h"
105 #include "HitTestResult.h"
106 #include "InspectorClient.h"
107 #include "InspectorController.h"
108 #include "InspectorDebuggableType.h"
109 #include "InspectorFrontendClientLocal.h"
110 #include "InspectorOverlay.h"
111 #include "InstrumentingAgents.h"
112 #include "IntRect.h"
113 #include "InternalSettings.h"
114 #include "InternalsMapLike.h"
115 #include "InternalsSetLike.h"
116 #include "JSDOMPromiseDeferred.h"
117 #include "JSImageData.h"
118 #include "LegacySchemeRegistry.h"
119 #include "LibWebRTCProvider.h"
120 #include "LoaderStrategy.h"
121 #include "Location.h"
122 #include "MallocStatistics.h"
123 #include "MediaDevices.h"
124 #include "MediaEngineConfigurationFactory.h"
125 #include "MediaPlayer.h"
126 #include "MediaProducer.h"
127 #include "MediaRecorderProvider.h"
128 #include "MediaResourceLoader.h"
129 #include "MediaStreamTrack.h"
130 #include "MediaUsageInfo.h"
131 #include "MemoryCache.h"
132 #include "MemoryInfo.h"
133 #include "MockAudioDestinationCocoa.h"
134 #include "MockLibWebRTCPeerConnection.h"
135 #include "MockPageOverlay.h"
136 #include "MockPageOverlayClient.h"
137 #include "NavigatorBeacon.h"
138 #include "NavigatorMediaDevices.h"
139 #include "NetworkLoadInformation.h"
140 #include "Page.h"
141 #include "PageOverlay.h"
142 #include "PathUtilities.h"
143 #include "PictureInPictureSupport.h"
144 #include "PlatformKeyboardEvent.h"
145 #include "PlatformMediaSessionManager.h"
146 #include "PlatformScreen.h"
147 #include "PlatformStrategies.h"
148 #include "PluginData.h"
149 #include "PrintContext.h"
150 #include "PseudoElement.h"
151 #include "Range.h"
152 #include "ReadableStream.h"
153 #include "RenderEmbeddedObject.h"
154 #include "RenderLayerBacking.h"
155 #include "RenderLayerCompositor.h"
156 #include "RenderMenuList.h"
157 #include "RenderTheme.h"
158 #include "RenderTreeAsText.h"
159 #include "RenderView.h"
160 #include "RenderedDocumentMarker.h"
161 #include "ResourceLoadObserver.h"
162 #include "RuntimeEnabledFeatures.h"
163 #include "SMILTimeContainer.h"
164 #include "SVGDocumentExtensions.h"
165 #include "SVGPathStringBuilder.h"
166 #include "SVGSVGElement.h"
167 #include "SWClientConnection.h"
168 #include "ScriptController.h"
169 #include "ScriptedAnimationController.h"
170 #include "ScrollingCoordinator.h"
171 #include "ScrollingMomentumCalculator.h"
172 #include "SecurityOrigin.h"
173 #include "SerializedScriptValue.h"
174 #include "ServiceWorker.h"
175 #include "ServiceWorkerProvider.h"
176 #include "ServiceWorkerRegistrationData.h"
177 #include "Settings.h"
178 #include "ShadowRoot.h"
179 #include "SourceBuffer.h"
180 #include "SpellChecker.h"
181 #include "StaticNodeList.h"
182 #include "StorageNamespace.h"
183 #include "StorageNamespaceProvider.h"
184 #include "StringCallback.h"
185 #include "StyleResolver.h"
186 #include "StyleRule.h"
187 #include "StyleScope.h"
188 #include "StyleSheetContents.h"
189 #include "TextIterator.h"
190 #include "TextPlaceholderElement.h"
191 #include "TreeScope.h"
192 #include "TypeConversions.h"
193 #include "UserGestureIndicator.h"
194 #include "UserMediaController.h"
195 #include "ViewportArguments.h"
196 #include "VoidCallback.h"
197 #include "WebAnimation.h"
198 #include "WebCoreJSClientData.h"
199 #include "WindowProxy.h"
200 #include "WorkerThread.h"
201 #include "WorkletGlobalScope.h"
202 #include "WritingDirection.h"
203 #include "XMLHttpRequest.h"
204 #include <JavaScriptCore/CodeBlock.h>
205 #include <JavaScriptCore/InspectorAgentBase.h>
206 #include <JavaScriptCore/InspectorFrontendChannel.h>
207 #include <JavaScriptCore/JSCInlines.h>
208 #include <JavaScriptCore/JSCJSValue.h>
209 #include <wtf/HexNumber.h>
210 #include <wtf/JSONValues.h>
211 #include <wtf/Language.h>
212 #include <wtf/MemoryPressureHandler.h>
213 #include <wtf/MonotonicTime.h>
214 #include <wtf/ProcessID.h>
215 #include <wtf/URLHelpers.h>
216 #include <wtf/text/StringBuilder.h>
217 #include <wtf/text/StringConcatenateNumbers.h>
218
219 #if USE(CG)
220 #include "PDFDocumentImage.h"
221 #endif
222
223 #if ENABLE(INPUT_TYPE_COLOR)
224 #include "ColorChooser.h"
225 #endif
226
227 #if ENABLE(MOUSE_CURSOR_SCALE)
228 #include <wtf/dtoa.h>
229 #endif
230
231 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
232 #include "LegacyCDM.h"
233 #include "LegacyMockCDM.h"
234 #endif
235
236 #if ENABLE(ENCRYPTED_MEDIA)
237 #include "MockCDMFactory.h"
238 #endif
239
240 #if ENABLE(VIDEO_TRACK)
241 #include "CaptionUserPreferences.h"
242 #include "PageGroup.h"
243 #include "TextTrack.h"
244 #include "TextTrackCueGeneric.h"
245 #endif
246
247 #if ENABLE(VIDEO)
248 #include "HTMLMediaElement.h"
249 #include "TimeRanges.h"
250 #endif
251
252 #if ENABLE(WEBGL)
253 #include "WebGLRenderingContext.h"
254 #endif
255
256 #if ENABLE(SPEECH_SYNTHESIS)
257 #include "DOMWindowSpeechSynthesis.h"
258 #include "PlatformSpeechSynthesizerMock.h"
259 #include "SpeechSynthesis.h"
260 #endif
261
262 #if ENABLE(MEDIA_STREAM)
263 #include "MediaRecorder.h"
264 #include "MediaRecorderPrivateMock.h"
265 #include "MediaStream.h"
266 #include "MockRealtimeMediaSourceCenter.h"
267 #endif
268
269 #if ENABLE(WEB_RTC)
270 #include "RTCPeerConnection.h"
271 #endif
272
273 #if ENABLE(MEDIA_SOURCE)
274 #include "MockMediaPlayerMediaSource.h"
275 #endif
276
277 #if ENABLE(CONTENT_FILTERING)
278 #include "MockContentFilterSettings.h"
279 #endif
280
281 #if ENABLE(WEB_AUDIO)
282 #include "AudioContext.h"
283 #endif
284
285 #if ENABLE(MEDIA_SESSION)
286 #include "MediaSession.h"
287 #include "MediaSessionManager.h"
288 #endif
289
290 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
291 #include "MediaPlaybackTargetContext.h"
292 #endif
293
294 #if ENABLE(POINTER_LOCK)
295 #include "PointerLockController.h"
296 #endif
297
298 #if ENABLE(INDEXED_DATABASE)
299 #include "IDBRequest.h"
300 #include "IDBTransaction.h"
301 #endif
302
303 #if USE(QUICK_LOOK)
304 #include "LegacyPreviewLoader.h"
305 #include "MockPreviewLoaderClient.h"
306 #endif
307
308 #if ENABLE(APPLE_PAY)
309 #include "MockPaymentCoordinator.h"
310 #include "PaymentCoordinator.h"
311 #endif
312
313 #if ENABLE(WEBXR)
314 #include "NavigatorWebXR.h"
315 #include "WebXRSystem.h"
316 #include "WebXRTest.h"
317 #endif
318
319 #if PLATFORM(MAC) && USE(LIBWEBRTC)
320 #include <webrtc/sdk/WebKit/VideoProcessingSoftLink.h>
321 #endif
322
323 #if PLATFORM(MAC)
324 #include "GraphicsContextGLOpenGLManager.h"
325 #include "NSScrollerImpDetails.h"
326 #include "ScrollbarThemeMac.h"
327 #endif
328
329 #if PLATFORM(COCOA)
330 #include "SystemBattery.h"
331 #include <wtf/spi/darwin/SandboxSPI.h>
332 #endif
333
334 using JSC::CallData;
335 using JSC::CodeBlock;
336 using JSC::FunctionExecutable;
337 using JSC::Identifier;
338 using JSC::JSFunction;
339 using JSC::JSGlobalObject;
340 using JSC::JSObject;
341 using JSC::JSValue;
342 using JSC::MarkedArgumentBuffer;
343 using JSC::PropertySlot;
344 using JSC::ScriptExecutable;
345 using JSC::StackVisitor;
346
347
348 namespace WebCore {
349 using namespace Inspector;
350
351 using namespace HTMLNames;
352
353 class InspectorStubFrontend final : public InspectorFrontendClientLocal, public FrontendChannel {
354 public:
355     InspectorStubFrontend(Page& inspectedPage, RefPtr<DOMWindow>&& frontendWindow);
356     virtual ~InspectorStubFrontend();
357
358 private:
359     bool supportsDockSide(DockSide) final { return false; }
360     void attachWindow(DockSide) final { }
361     void detachWindow() final { }
362     void closeWindow() final;
363     void reopen() final { }
364     void bringToFront() final { }
365     void setForcedAppearance(InspectorFrontendClient::Appearance) final { }
366     String localizedStringsURL() const final { return String(); }
367     DebuggableType debuggableType() const final { return DebuggableType::Page; }
368     String targetPlatformName() const { return "Unknown"_s; }
369     String targetBuildVersion() const { return "Unknown"_s; }
370     String targetProductVersion() const { return "Unknown"_s; }
371     bool targetIsSimulator() const { return false; }
372     void inspectedURLChanged(const String&) final { }
373     void showCertificate(const CertificateInfo&) final { }
374     void setAttachedWindowHeight(unsigned) final { }
375     void setAttachedWindowWidth(unsigned) final { }
376     void setSheetRect(const FloatRect&) final { }
377
378     void sendMessageToFrontend(const String& message) final;
379     ConnectionType connectionType() const final { return ConnectionType::Local; }
380
381     RefPtr<DOMWindow> m_frontendWindow;
382 };
383
384 InspectorStubFrontend::InspectorStubFrontend(Page& inspectedPage, RefPtr<DOMWindow>&& frontendWindow)
385     : InspectorFrontendClientLocal(&inspectedPage.inspectorController(), frontendWindow->document()->page(), makeUnique<InspectorFrontendClientLocal::Settings>())
386     , m_frontendWindow(frontendWindow.copyRef())
387 {
388     ASSERT_ARG(frontendWindow, frontendWindow);
389
390     frontendPage()->inspectorController().setInspectorFrontendClient(this);
391     inspectedPage.inspectorController().connectFrontend(*this);
392 }
393
394 InspectorStubFrontend::~InspectorStubFrontend()
395 {
396     closeWindow();
397 }
398
399 void InspectorStubFrontend::closeWindow()
400 {
401     if (!m_frontendWindow)
402         return;
403
404     frontendPage()->inspectorController().setInspectorFrontendClient(nullptr);
405     inspectedPage()->inspectorController().disconnectFrontend(*this);
406
407     m_frontendWindow->close();
408     m_frontendWindow = nullptr;
409 }
410
411 void InspectorStubFrontend::sendMessageToFrontend(const String& message)
412 {
413     dispatchMessageAsync(message);
414 }
415
416 static bool markerTypeFrom(const String& markerType, DocumentMarker::MarkerType& result)
417 {
418     if (equalLettersIgnoringASCIICase(markerType, "spelling"))
419         result = DocumentMarker::Spelling;
420     else if (equalLettersIgnoringASCIICase(markerType, "grammar"))
421         result = DocumentMarker::Grammar;
422     else if (equalLettersIgnoringASCIICase(markerType, "textmatch"))
423         result = DocumentMarker::TextMatch;
424     else if (equalLettersIgnoringASCIICase(markerType, "replacement"))
425         result = DocumentMarker::Replacement;
426     else if (equalLettersIgnoringASCIICase(markerType, "correctionindicator"))
427         result = DocumentMarker::CorrectionIndicator;
428     else if (equalLettersIgnoringASCIICase(markerType, "rejectedcorrection"))
429         result = DocumentMarker::RejectedCorrection;
430     else if (equalLettersIgnoringASCIICase(markerType, "autocorrected"))
431         result = DocumentMarker::Autocorrected;
432     else if (equalLettersIgnoringASCIICase(markerType, "spellcheckingexemption"))
433         result = DocumentMarker::SpellCheckingExemption;
434     else if (equalLettersIgnoringASCIICase(markerType, "deletedautocorrection"))
435         result = DocumentMarker::DeletedAutocorrection;
436     else if (equalLettersIgnoringASCIICase(markerType, "dictationalternatives"))
437         result = DocumentMarker::DictationAlternatives;
438 #if ENABLE(TELEPHONE_NUMBER_DETECTION)
439     else if (equalLettersIgnoringASCIICase(markerType, "telephonenumber"))
440         result = DocumentMarker::TelephoneNumber;
441 #endif
442     else
443         return false;
444
445     return true;
446 }
447
448 static bool markerTypesFrom(const String& markerType, OptionSet<DocumentMarker::MarkerType>& result)
449 {
450     DocumentMarker::MarkerType singularResult;
451
452     if (markerType.isEmpty() || equalLettersIgnoringASCIICase(markerType, "all"))
453         result = DocumentMarker::allMarkers();
454     else if (markerTypeFrom(markerType, singularResult))
455         result = singularResult;
456     else
457         return false;
458
459     return true;
460 }
461
462 static std::unique_ptr<PrintContext>& printContextForTesting()
463 {
464     static NeverDestroyed<std::unique_ptr<PrintContext>> context;
465     return context;
466 }
467
468 const char* Internals::internalsId = "internals";
469
470 Ref<Internals> Internals::create(Document& document)
471 {
472     return adoptRef(*new Internals(document));
473 }
474
475 Internals::~Internals()
476 {
477 #if ENABLE(MEDIA_STREAM)
478     if (m_trackSource) {
479         m_trackSource->removeObserver(*this);
480         m_trackSource->removeAudioSampleObserver(*this);
481     }
482 #endif
483 }
484
485 void Internals::resetToConsistentState(Page& page)
486 {
487     page.setPageScaleFactor(1, IntPoint(0, 0));
488     page.setPagination(Pagination());
489     page.setPaginationLineGridEnabled(false);
490
491     page.setDefersLoading(false);
492
493     page.mainFrame().setTextZoomFactor(1.0f);
494
495     page.setCompositingPolicyOverride(WebCore::CompositingPolicy::Normal);
496
497     FrameView* mainFrameView = page.mainFrame().view();
498     if (mainFrameView) {
499         page.setHeaderHeight(0);
500         page.setFooterHeight(0);
501         page.setTopContentInset(0);
502         mainFrameView->setUseFixedLayout(false);
503         mainFrameView->setFixedLayoutSize(IntSize());
504         mainFrameView->enableFixedWidthAutoSizeMode(false, { });
505 #if USE(COORDINATED_GRAPHICS)
506         mainFrameView->setFixedVisibleContentRect(IntRect());
507 #endif
508         if (auto* backing = mainFrameView->tiledBacking())
509             backing->setTileSizeUpdateDelayDisabledForTesting(false);
510     }
511
512     WTF::clearDefaultPortForProtocolMapForTesting();
513     overrideUserPreferredLanguages(Vector<String>());
514     WebCore::DeprecatedGlobalSettings::setUsesOverlayScrollbars(false);
515     WebCore::DeprecatedGlobalSettings::setUsesMockScrollAnimator(false);
516 #if ENABLE(VIDEO_TRACK)
517     page.group().captionPreferences().setTestingMode(true);
518     page.group().captionPreferences().setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
519     page.group().captionPreferences().setCaptionsStyleSheetOverride(emptyString());
520     page.group().captionPreferences().setTestingMode(false);
521 #endif
522     if (!page.mainFrame().editor().isContinuousSpellCheckingEnabled())
523         page.mainFrame().editor().toggleContinuousSpellChecking();
524     if (page.mainFrame().editor().isOverwriteModeEnabled())
525         page.mainFrame().editor().toggleOverwriteModeEnabled();
526     page.mainFrame().loader().clearTestingOverrides();
527     page.applicationCacheStorage().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
528 #if ENABLE(VIDEO)
529     PlatformMediaSessionManager::sharedManager().resetRestrictions();
530     PlatformMediaSessionManager::sharedManager().setWillIgnoreSystemInterruptions(true);
531 #endif
532 #if ENABLE(VIDEO) || ENABLE(WEB_AUDIO)
533     PlatformMediaSessionManager::sharedManager().setIsPlayingToAutomotiveHeadUnit(false);
534 #endif
535 #if ENABLE(ACCESSIBILITY)
536     AXObjectCache::setEnhancedUserInterfaceAccessibility(false);
537     AXObjectCache::disableAccessibility();
538 #endif
539
540     MockPageOverlayClient::singleton().uninstallAllOverlays();
541
542 #if ENABLE(CONTENT_FILTERING)
543     MockContentFilterSettings::reset();
544 #endif
545
546 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
547     page.setMockMediaPlaybackTargetPickerEnabled(true);
548     page.setMockMediaPlaybackTargetPickerState(emptyString(), MediaPlaybackTargetContext::Unknown);
549 #endif
550
551     MediaResourceLoader::recordResponsesForTesting();
552
553     page.setShowAllPlugins(false);
554     page.setLowPowerModeEnabledOverrideForTesting(WTF::nullopt);
555
556 #if USE(QUICK_LOOK)
557     MockPreviewLoaderClient::singleton().setPassword("");
558     LegacyPreviewLoader::setClientForTesting(nullptr);
559 #endif
560
561     printContextForTesting() = nullptr;
562
563 #if USE(LIBWEBRTC)
564     auto& rtcProvider = page.libWebRTCProvider();
565     WebCore::useRealRTCPeerConnectionFactory(rtcProvider);
566     rtcProvider.disableNonLocalhostConnections();
567     RuntimeEnabledFeatures::sharedFeatures().setWebRTCH265CodecEnabled(true);
568     page.settings().setWebRTCEncryptionEnabled(true);
569 #endif
570
571     page.setFullscreenAutoHideDuration(0_s);
572     page.setFullscreenInsets({ });
573     page.setFullscreenControlsHidden(false);
574
575     MediaEngineConfigurationFactory::disableMock();
576
577 #if ENABLE(MEDIA_STREAM)
578     RuntimeEnabledFeatures::sharedFeatures().setInterruptAudioOnPageVisibilityChangeEnabled(false);
579     WebCore::MediaRecorder::setCustomPrivateRecorderCreator(nullptr);
580     page.mediaRecorderProvider().setUseGPUProcess(true);
581 #endif
582
583     HTMLCanvasElement::setMaxPixelMemoryForTesting(0); // This means use the default value.
584     DOMWindow::overrideTransientActivationDurationForTesting(WTF::nullopt);
585 }
586
587 Internals::Internals(Document& document)
588     : ContextDestructionObserver(&document)
589 #if ENABLE(MEDIA_STREAM)
590     , m_orientationNotifier(0)
591 #endif
592 {
593 #if ENABLE(VIDEO_TRACK)
594     if (document.page())
595         document.page()->group().captionPreferences().setTestingMode(true);
596 #endif
597
598 #if ENABLE(MEDIA_STREAM)
599     setMediaCaptureRequiresSecureConnection(false);
600 #endif
601
602 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
603     if (document.page())
604         document.page()->setMockMediaPlaybackTargetPickerEnabled(true);
605 #endif
606
607     if (contextDocument() && contextDocument()->frame()) {
608         setAutomaticSpellingCorrectionEnabled(true);
609         setAutomaticQuoteSubstitutionEnabled(false);
610         setAutomaticDashSubstitutionEnabled(false);
611         setAutomaticLinkDetectionEnabled(false);
612         setAutomaticTextReplacementEnabled(true);
613     }
614
615     setConsoleMessageListener(nullptr);
616
617 #if ENABLE(APPLE_PAY)
618     auto* frame = document.frame();
619     if (frame && frame->page() && frame->isMainFrame()) {
620         auto mockPaymentCoordinator = new MockPaymentCoordinator(*frame->page());
621         frame->page()->setPaymentCoordinator(makeUnique<PaymentCoordinator>(*mockPaymentCoordinator));
622     }
623 #endif
624
625 #if PLATFORM(COCOA) &&  ENABLE(WEB_AUDIO)
626     AudioDestinationCocoa::createOverride = nullptr;
627 #endif
628 }
629
630 Document* Internals::contextDocument() const
631 {
632     return downcast<Document>(scriptExecutionContext());
633 }
634
635 Frame* Internals::frame() const
636 {
637     if (!contextDocument())
638         return nullptr;
639     return contextDocument()->frame();
640 }
641
642 InternalSettings* Internals::settings() const
643 {
644     Document* document = contextDocument();
645     if (!document)
646         return nullptr;
647     Page* page = document->page();
648     if (!page)
649         return nullptr;
650     return InternalSettings::from(page);
651 }
652
653 unsigned Internals::inflightBeaconsCount() const
654 {
655     auto* document = contextDocument();
656     if (!document)
657         return 0;
658
659     auto* window = document->domWindow();
660     if (!window)
661         return 0;
662
663     auto* navigator = window->optionalNavigator();
664     if (!navigator)
665         return 0;
666
667     return NavigatorBeacon::from(*navigator)->inflightBeaconsCount();
668 }
669
670 unsigned Internals::workerThreadCount() const
671 {
672     return WorkerThread::workerThreadCount();
673 }
674
675 ExceptionOr<bool> Internals::areSVGAnimationsPaused() const
676 {
677     auto* document = contextDocument();
678     if (!document)
679         return Exception { InvalidAccessError, "No context document"_s };
680
681     if (!document->svgExtensions())
682         return Exception { NotFoundError, "No SVG animations"_s };
683
684     return document->accessSVGExtensions().areAnimationsPaused();
685 }
686
687 ExceptionOr<double> Internals::svgAnimationsInterval(SVGSVGElement& element) const
688 {
689     auto* document = contextDocument();
690     if (!document)
691         return 0;
692
693     if (!document->svgExtensions())
694         return 0;
695
696     if (document->accessSVGExtensions().areAnimationsPaused())
697         return 0;
698
699     return element.timeContainer().animationFrameDelay().value();
700 }
701
702 String Internals::address(Node& node)
703 {
704     return makeString("0x", hex(reinterpret_cast<uintptr_t>(&node)));
705 }
706
707 bool Internals::nodeNeedsStyleRecalc(Node& node)
708 {
709     return node.needsStyleRecalc();
710 }
711
712 static String styleValidityToToString(Style::Validity validity)
713 {
714     switch (validity) {
715     case Style::Validity::Valid:
716         return "NoStyleChange";
717     case Style::Validity::ElementInvalid:
718         return "InlineStyleChange";
719     case Style::Validity::SubtreeInvalid:
720         return "FullStyleChange";
721     case Style::Validity::SubtreeAndRenderersInvalid:
722         return "ReconstructRenderTree";
723     }
724     ASSERT_NOT_REACHED();
725     return "";
726 }
727
728 String Internals::styleChangeType(Node& node)
729 {
730     node.document().styleScope().flushPendingUpdate();
731
732     return styleValidityToToString(node.styleValidity());
733 }
734
735 String Internals::description(JSC::JSValue value)
736 {
737     return toString(value);
738 }
739
740 bool Internals::isPreloaded(const String& url)
741 {
742     Document* document = contextDocument();
743     return document->cachedResourceLoader().isPreloaded(url);
744 }
745
746 bool Internals::isLoadingFromMemoryCache(const String& url)
747 {
748     if (!contextDocument() || !contextDocument()->page())
749         return false;
750
751     ResourceRequest request(contextDocument()->completeURL(url));
752     request.setDomainForCachePartition(contextDocument()->domainForCachePartition());
753
754     CachedResource* resource = MemoryCache::singleton().resourceForRequest(request, contextDocument()->page()->sessionID());
755     return resource && resource->status() == CachedResource::Cached;
756 }
757
758 static String responseSourceToString(const ResourceResponse& response)
759 {
760     if (response.isNull())
761         return "Null response";
762     switch (response.source()) {
763     case ResourceResponse::Source::Unknown:
764         return "Unknown";
765     case ResourceResponse::Source::Network:
766         return "Network";
767     case ResourceResponse::Source::ServiceWorker:
768         return "Service worker";
769     case ResourceResponse::Source::DiskCache:
770         return "Disk cache";
771     case ResourceResponse::Source::DiskCacheAfterValidation:
772         return "Disk cache after validation";
773     case ResourceResponse::Source::MemoryCache:
774         return "Memory cache";
775     case ResourceResponse::Source::MemoryCacheAfterValidation:
776         return "Memory cache after validation";
777     case ResourceResponse::Source::ApplicationCache:
778         return "Application cache";
779     case ResourceResponse::Source::DOMCache:
780         return "DOM cache";
781     case ResourceResponse::Source::InspectorOverride:
782         return "Inspector override";
783     }
784     ASSERT_NOT_REACHED();
785     return "Error";
786 }
787
788 String Internals::xhrResponseSource(XMLHttpRequest& request)
789 {
790     return responseSourceToString(request.resourceResponse());
791 }
792
793 String Internals::fetchResponseSource(FetchResponse& response)
794 {
795     return responseSourceToString(response.resourceResponse());
796 }
797
798 bool Internals::isSharingStyleSheetContents(HTMLLinkElement& a, HTMLLinkElement& b)
799 {
800     if (!a.sheet() || !b.sheet())
801         return false;
802     return &a.sheet()->contents() == &b.sheet()->contents();
803 }
804
805 bool Internals::isStyleSheetLoadingSubresources(HTMLLinkElement& link)
806 {
807     return link.sheet() && link.sheet()->contents().isLoadingSubresources();
808 }
809
810 static ResourceRequestCachePolicy toResourceRequestCachePolicy(Internals::CachePolicy policy)
811 {
812     switch (policy) {
813     case Internals::CachePolicy::UseProtocolCachePolicy:
814         return ResourceRequestCachePolicy::UseProtocolCachePolicy;
815     case Internals::CachePolicy::ReloadIgnoringCacheData:
816         return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
817     case Internals::CachePolicy::ReturnCacheDataElseLoad:
818         return ResourceRequestCachePolicy::ReturnCacheDataElseLoad;
819     case Internals::CachePolicy::ReturnCacheDataDontLoad:
820         return ResourceRequestCachePolicy::ReturnCacheDataDontLoad;
821     }
822     ASSERT_NOT_REACHED();
823     return ResourceRequestCachePolicy::UseProtocolCachePolicy;
824 }
825
826 void Internals::setOverrideCachePolicy(CachePolicy policy)
827 {
828     frame()->loader().setOverrideCachePolicyForTesting(toResourceRequestCachePolicy(policy));
829 }
830
831 ExceptionOr<void> Internals::setCanShowModalDialogOverride(bool allow)
832 {
833     if (!contextDocument() || !contextDocument()->domWindow())
834         return Exception { InvalidAccessError };
835
836     contextDocument()->domWindow()->setCanShowModalDialogOverride(allow);
837     return { };
838 }
839
840 static ResourceLoadPriority toResourceLoadPriority(Internals::ResourceLoadPriority priority)
841 {
842     switch (priority) {
843     case Internals::ResourceLoadPriority::ResourceLoadPriorityVeryLow:
844         return ResourceLoadPriority::VeryLow;
845     case Internals::ResourceLoadPriority::ResourceLoadPriorityLow:
846         return ResourceLoadPriority::Low;
847     case Internals::ResourceLoadPriority::ResourceLoadPriorityMedium:
848         return ResourceLoadPriority::Medium;
849     case Internals::ResourceLoadPriority::ResourceLoadPriorityHigh:
850         return ResourceLoadPriority::High;
851     case Internals::ResourceLoadPriority::ResourceLoadPriorityVeryHigh:
852         return ResourceLoadPriority::VeryHigh;
853     }
854     ASSERT_NOT_REACHED();
855     return ResourceLoadPriority::Low;
856 }
857
858 void Internals::setOverrideResourceLoadPriority(ResourceLoadPriority priority)
859 {
860     frame()->loader().setOverrideResourceLoadPriorityForTesting(toResourceLoadPriority(priority));
861 }
862
863 void Internals::setStrictRawResourceValidationPolicyDisabled(bool disabled)
864 {
865     frame()->loader().setStrictRawResourceValidationPolicyDisabledForTesting(disabled);
866 }
867
868 void Internals::clearMemoryCache()
869 {
870     MemoryCache::singleton().evictResources();
871 }
872
873 void Internals::pruneMemoryCacheToSize(unsigned size)
874 {
875     MemoryCache::singleton().pruneDeadResourcesToSize(size);
876     MemoryCache::singleton().pruneLiveResourcesToSize(size, true);
877 }
878     
879 void Internals::destroyDecodedDataForAllImages()
880 {
881     MemoryCache::singleton().destroyDecodedDataForAllImages();
882 }
883
884 unsigned Internals::memoryCacheSize() const
885 {
886     return MemoryCache::singleton().size();
887 }
888
889 static Image* imageFromImageElement(HTMLImageElement& element)
890 {
891     auto* cachedImage = element.cachedImage();
892     return cachedImage ? cachedImage->image() : nullptr;
893 }
894
895 static BitmapImage* bitmapImageFromImageElement(HTMLImageElement& element)
896 {
897     auto* image = imageFromImageElement(element);
898     return image && is<BitmapImage>(image) ? &downcast<BitmapImage>(*image) : nullptr;
899 }
900
901 #if USE(CG)
902 static PDFDocumentImage* pdfDocumentImageFromImageElement(HTMLImageElement& element)
903 {
904     auto* image = imageFromImageElement(element);
905     return image && is<PDFDocumentImage>(image) ? &downcast<PDFDocumentImage>(*image) : nullptr;
906 }
907 #endif
908
909 unsigned Internals::imageFrameIndex(HTMLImageElement& element)
910 {
911     auto* bitmapImage = bitmapImageFromImageElement(element);
912     return bitmapImage ? bitmapImage->currentFrame() : 0;
913 }
914
915 unsigned Internals::imageFrameCount(HTMLImageElement& element)
916 {
917     auto* bitmapImage = bitmapImageFromImageElement(element);
918     return bitmapImage ? bitmapImage->frameCount() : 0;
919 }
920
921 float Internals::imageFrameDurationAtIndex(HTMLImageElement& element, unsigned index)
922 {
923     auto* bitmapImage = bitmapImageFromImageElement(element);
924     return bitmapImage ? bitmapImage->frameDurationAtIndex(index).value() : 0;
925 }
926     
927 void Internals::setImageFrameDecodingDuration(HTMLImageElement& element, float duration)
928 {
929     if (auto* bitmapImage = bitmapImageFromImageElement(element))
930         bitmapImage->setFrameDecodingDurationForTesting(Seconds { duration });
931 }
932
933 void Internals::resetImageAnimation(HTMLImageElement& element)
934 {
935     if (auto* image = imageFromImageElement(element))
936         image->resetAnimation();
937 }
938
939 bool Internals::isImageAnimating(HTMLImageElement& element)
940 {
941     auto* image = imageFromImageElement(element);
942     return image && (image->isAnimating() || image->animationPending());
943 }
944
945 unsigned Internals::imagePendingDecodePromisesCountForTesting(HTMLImageElement& element)
946 {
947     return element.pendingDecodePromisesCountForTesting();
948 }
949
950 void Internals::setClearDecoderAfterAsyncFrameRequestForTesting(HTMLImageElement& element, bool enabled)
951 {
952     if (auto* bitmapImage = bitmapImageFromImageElement(element))
953         bitmapImage->setClearDecoderAfterAsyncFrameRequestForTesting(enabled);
954 }
955
956 unsigned Internals::imageDecodeCount(HTMLImageElement& element)
957 {
958     auto* bitmapImage = bitmapImageFromImageElement(element);
959     return bitmapImage ? bitmapImage->decodeCountForTesting() : 0;
960 }
961
962 unsigned Internals::pdfDocumentCachingCount(HTMLImageElement& element)
963 {
964 #if USE(CG)
965     auto* pdfDocumentImage = pdfDocumentImageFromImageElement(element);
966     return pdfDocumentImage ? pdfDocumentImage->cachingCountForTesting() : 0;
967 #else
968     UNUSED_PARAM(element);
969     return 0;
970 #endif
971 }
972
973 void Internals::setLargeImageAsyncDecodingEnabledForTesting(HTMLImageElement& element, bool enabled)
974 {
975     if (auto* bitmapImage = bitmapImageFromImageElement(element))
976         bitmapImage->setLargeImageAsyncDecodingEnabledForTesting(enabled);
977 }
978     
979 void Internals::setForceUpdateImageDataEnabledForTesting(HTMLImageElement& element, bool enabled)
980 {
981     if (auto* cachedImage = element.cachedImage())
982         cachedImage->setForceUpdateImageDataEnabledForTesting(enabled);
983 }
984
985 void Internals::setGridMaxTracksLimit(unsigned maxTrackLimit)
986 {
987     GridPosition::setMaxPositionForTesting(maxTrackLimit);
988 }
989
990 void Internals::clearBackForwardCache()
991 {
992     BackForwardCache::singleton().pruneToSizeNow(0, PruningReason::None);
993 }
994
995 unsigned Internals::backForwardCacheSize() const
996 {
997     return BackForwardCache::singleton().pageCount();
998 }
999
1000 void Internals::preventDocumentFromEnteringBackForwardCache()
1001 {
1002     if (auto* document = contextDocument())
1003         document->preventEnteringBackForwardCacheForTesting();
1004 }
1005
1006 void Internals::disableTileSizeUpdateDelay()
1007 {
1008     Document* document = contextDocument();
1009     if (!document || !document->frame())
1010         return;
1011
1012     auto* view = document->frame()->view();
1013     if (!view)
1014         return;
1015
1016     if (auto* backing = view->tiledBacking())
1017         backing->setTileSizeUpdateDelayDisabledForTesting(true);
1018 }
1019
1020 void Internals::setSpeculativeTilingDelayDisabledForTesting(bool disabled)
1021 {
1022     Document* document = contextDocument();
1023     if (!document || !document->frame())
1024         return;
1025
1026     if (auto* frameView = document->frame()->view())
1027         frameView->setSpeculativeTilingDelayDisabledForTesting(disabled);
1028 }
1029
1030
1031 Node* Internals::treeScopeRootNode(Node& node)
1032 {
1033     return &node.treeScope().rootNode();
1034 }
1035
1036 Node* Internals::parentTreeScope(Node& node)
1037 {
1038     const TreeScope* parentTreeScope = node.treeScope().parentTreeScope();
1039     return parentTreeScope ? &parentTreeScope->rootNode() : nullptr;
1040 }
1041
1042 ExceptionOr<unsigned> Internals::lastSpatialNavigationCandidateCount() const
1043 {
1044     if (!contextDocument() || !contextDocument()->page())
1045         return Exception { InvalidAccessError };
1046
1047     return contextDocument()->page()->lastSpatialNavigationCandidateCount();
1048 }
1049
1050 bool Internals::animationWithIdExists(const String& id) const
1051 {
1052     for (auto* animation : WebAnimation::instances()) {
1053         if (animation->id() == id)
1054             return true;
1055     }
1056     return false;
1057 }
1058
1059 unsigned Internals::numberOfActiveAnimations() const
1060 {
1061     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
1062         return frame()->document()->timeline().numberOfActiveAnimationsForTesting();
1063     return frame()->legacyAnimation().numberOfActiveAnimations(frame()->document());
1064 }
1065
1066 ExceptionOr<bool> Internals::animationsAreSuspended() const
1067 {
1068     Document* document = contextDocument();
1069     if (!document || !document->frame())
1070         return Exception { InvalidAccessError };
1071
1072     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
1073         return document->timeline().animationsAreSuspended();
1074     return document->frame()->legacyAnimation().animationsAreSuspendedForDocument(document);
1075 }
1076
1077 double Internals::animationsInterval() const
1078 {
1079     Document* document = contextDocument();
1080     if (!document)
1081         return INFINITY;
1082
1083     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
1084         if (auto timeline = document->existingTimeline())
1085             return timeline->animationInterval().seconds();
1086         return INFINITY;
1087     }
1088
1089     if (!document->frame())
1090         return INFINITY;
1091     return document->frame()->legacyAnimation().animationInterval().value();
1092 }
1093
1094 ExceptionOr<void> Internals::suspendAnimations() const
1095 {
1096     Document* document = contextDocument();
1097     if (!document || !document->frame())
1098         return Exception { InvalidAccessError };
1099
1100     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
1101         document->timeline().suspendAnimations();
1102         for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
1103             if (Document* document = frame->document())
1104                 document->timeline().suspendAnimations();
1105         }
1106     } else {
1107         document->frame()->legacyAnimation().suspendAnimationsForDocument(document);
1108
1109         for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
1110             if (Document* document = frame->document())
1111                 frame->legacyAnimation().suspendAnimationsForDocument(document);
1112         }
1113     }
1114
1115     return { };
1116 }
1117
1118 ExceptionOr<void> Internals::resumeAnimations() const
1119 {
1120     Document* document = contextDocument();
1121     if (!document || !document->frame())
1122         return Exception { InvalidAccessError };
1123
1124     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled()) {
1125         document->timeline().resumeAnimations();
1126         for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
1127             if (Document* document = frame->document())
1128                 document->timeline().resumeAnimations();
1129         }
1130     } else {
1131         document->frame()->legacyAnimation().resumeAnimationsForDocument(document);
1132
1133         for (Frame* frame = document->frame(); frame; frame = frame->tree().traverseNext()) {
1134             if (Document* document = frame->document())
1135                 frame->legacyAnimation().resumeAnimationsForDocument(document);
1136         }
1137     }
1138
1139     return { };
1140 }
1141
1142 ExceptionOr<bool> Internals::pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element& element)
1143 {
1144     if (pauseTime < 0)
1145         return Exception { InvalidAccessError };
1146     return frame()->legacyAnimation().pauseAnimationAtTime(element, AtomString(animationName), pauseTime);
1147 }
1148
1149 ExceptionOr<bool> Internals::pauseAnimationAtTimeOnPseudoElement(const String& animationName, double pauseTime, Element& element, const String& pseudoId)
1150 {
1151     if (pauseTime < 0)
1152         return Exception { InvalidAccessError };
1153
1154     if (pseudoId != "before" && pseudoId != "after")
1155         return Exception { InvalidAccessError };
1156
1157     PseudoElement* pseudoElement = pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
1158     if (!pseudoElement)
1159         return Exception { InvalidAccessError };
1160
1161     return frame()->legacyAnimation().pauseAnimationAtTime(*pseudoElement, AtomString(animationName), pauseTime);
1162 }
1163
1164 ExceptionOr<bool> Internals::pauseTransitionAtTimeOnElement(const String& propertyName, double pauseTime, Element& element)
1165 {
1166     if (pauseTime < 0)
1167         return Exception { InvalidAccessError };
1168     return frame()->legacyAnimation().pauseTransitionAtTime(element, propertyName, pauseTime);
1169 }
1170
1171 ExceptionOr<bool> Internals::pauseTransitionAtTimeOnPseudoElement(const String& property, double pauseTime, Element& element, const String& pseudoId)
1172 {
1173     if (pauseTime < 0)
1174         return Exception { InvalidAccessError };
1175
1176     if (pseudoId != "before" && pseudoId != "after")
1177         return Exception { InvalidAccessError };
1178
1179     PseudoElement* pseudoElement = pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
1180     if (!pseudoElement)
1181         return Exception { InvalidAccessError };
1182
1183     return frame()->legacyAnimation().pauseTransitionAtTime(*pseudoElement, property, pauseTime);
1184 }
1185
1186 Vector<Internals::AcceleratedAnimation> Internals::acceleratedAnimationsForElement(Element& element)
1187 {
1188     if (!RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
1189         return { };
1190
1191     Vector<Internals::AcceleratedAnimation> animations;
1192     for (const auto& animationAsPair : element.document().timeline().acceleratedAnimationsForElement(element))
1193         animations.append({ animationAsPair.first, animationAsPair.second });
1194     return animations;
1195 }
1196
1197 unsigned Internals::numberOfAnimationTimelineInvalidations() const
1198 {
1199     if (RuntimeEnabledFeatures::sharedFeatures().webAnimationsCSSIntegrationEnabled())
1200         return frame()->document()->timeline().numberOfAnimationTimelineInvalidationsForTesting();
1201     return 0;
1202 }
1203
1204 ExceptionOr<RefPtr<Element>> Internals::pseudoElement(Element& element, const String& pseudoId)
1205 {
1206     if (pseudoId != "before" && pseudoId != "after")
1207         return Exception { InvalidAccessError };
1208
1209     return pseudoId == "before" ? element.beforePseudoElement() : element.afterPseudoElement();
1210 }
1211
1212 ExceptionOr<String> Internals::elementRenderTreeAsText(Element& element)
1213 {
1214     element.document().updateStyleIfNeeded();
1215
1216     String representation = externalRepresentation(&element);
1217     if (representation.isEmpty())
1218         return Exception { InvalidAccessError };
1219
1220     return representation;
1221 }
1222
1223 bool Internals::hasPausedImageAnimations(Element& element)
1224 {
1225     return element.renderer() && element.renderer()->hasPausedImageAnimations();
1226 }
1227     
1228 bool Internals::isPaintingFrequently(Element& element)
1229 {
1230     return element.renderer() && element.renderer()->enclosingLayer() && element.renderer()->enclosingLayer()->paintingFrequently();
1231 }
1232
1233 void Internals::incrementFrequentPaintCounter(Element& element)
1234 {
1235     if (element.renderer() && element.renderer()->enclosingLayer())
1236         element.renderer()->enclosingLayer()->simulateFrequentPaint();
1237 }
1238
1239 Ref<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Element& element) const
1240 {
1241     bool allowVisitedStyle = true;
1242     return CSSComputedStyleDeclaration::create(element, allowVisitedStyle);
1243 }
1244
1245 Node* Internals::ensureUserAgentShadowRoot(Element& host)
1246 {
1247     return &host.ensureUserAgentShadowRoot();
1248 }
1249
1250 Node* Internals::shadowRoot(Element& host)
1251 {
1252     return host.shadowRoot();
1253 }
1254
1255 ExceptionOr<String> Internals::shadowRootType(const Node& root) const
1256 {
1257     if (!is<ShadowRoot>(root))
1258         return Exception { InvalidAccessError };
1259
1260     switch (downcast<ShadowRoot>(root).mode()) {
1261     case ShadowRootMode::UserAgent:
1262         return "UserAgentShadowRoot"_str;
1263     case ShadowRootMode::Closed:
1264         return "ClosedShadowRoot"_str;
1265     case ShadowRootMode::Open:
1266         return "OpenShadowRoot"_str;
1267     default:
1268         ASSERT_NOT_REACHED();
1269         return "Unknown"_str;
1270     }
1271 }
1272
1273 String Internals::shadowPseudoId(Element& element)
1274 {
1275     return element.shadowPseudoId().string();
1276 }
1277
1278 void Internals::setShadowPseudoId(Element& element, const String& id)
1279 {
1280     return element.setPseudo(id);
1281 }
1282
1283 static unsigned deferredStyleRulesCountForList(const Vector<RefPtr<StyleRuleBase>>& childRules)
1284 {
1285     unsigned count = 0;
1286     for (auto rule : childRules) {
1287         if (is<StyleRule>(rule)) {
1288             auto* cssRule = downcast<StyleRule>(rule.get());
1289             if (!cssRule->propertiesWithoutDeferredParsing())
1290                 count++;
1291             continue;
1292         }
1293
1294         StyleRuleGroup* groupRule = nullptr;
1295         if (is<StyleRuleMedia>(rule))
1296             groupRule = downcast<StyleRuleMedia>(rule.get());
1297         else if (is<StyleRuleSupports>(rule))
1298             groupRule = downcast<StyleRuleSupports>(rule.get());
1299         if (!groupRule)
1300             continue;
1301
1302         auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
1303         if (!groupChildRules)
1304             continue;
1305
1306         count += deferredStyleRulesCountForList(*groupChildRules);
1307     }
1308
1309     return count;
1310 }
1311
1312 unsigned Internals::deferredStyleRulesCount(StyleSheet& styleSheet)
1313 {
1314     return deferredStyleRulesCountForList(downcast<CSSStyleSheet>(styleSheet).contents().childRules());
1315 }
1316
1317 static unsigned deferredGroupRulesCountForList(const Vector<RefPtr<StyleRuleBase>>& childRules)
1318 {
1319     unsigned count = 0;
1320     for (auto rule : childRules) {
1321         StyleRuleGroup* groupRule = nullptr;
1322         if (is<StyleRuleMedia>(rule))
1323             groupRule = downcast<StyleRuleMedia>(rule.get());
1324         else if (is<StyleRuleSupports>(rule))
1325             groupRule = downcast<StyleRuleSupports>(rule.get());
1326         if (!groupRule)
1327             continue;
1328
1329         auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
1330         if (!groupChildRules)
1331             count++;
1332         else
1333             count += deferredGroupRulesCountForList(*groupChildRules);
1334     }
1335     return count;
1336 }
1337
1338 unsigned Internals::deferredGroupRulesCount(StyleSheet& styleSheet)
1339 {
1340     return deferredGroupRulesCountForList(downcast<CSSStyleSheet>(styleSheet).contents().childRules());
1341 }
1342
1343 static unsigned deferredKeyframesRulesCountForList(const Vector<RefPtr<StyleRuleBase>>& childRules)
1344 {
1345     unsigned count = 0;
1346     for (auto rule : childRules) {
1347         if (is<StyleRuleKeyframes>(rule)) {
1348             auto* cssRule = downcast<StyleRuleKeyframes>(rule.get());
1349             if (!cssRule->keyframesWithoutDeferredParsing())
1350                 count++;
1351             continue;
1352         }
1353
1354         StyleRuleGroup* groupRule = nullptr;
1355         if (is<StyleRuleMedia>(rule))
1356             groupRule = downcast<StyleRuleMedia>(rule.get());
1357         else if (is<StyleRuleSupports>(rule))
1358             groupRule = downcast<StyleRuleSupports>(rule.get());
1359         if (!groupRule)
1360             continue;
1361
1362         auto* groupChildRules = groupRule->childRulesWithoutDeferredParsing();
1363         if (!groupChildRules)
1364             continue;
1365
1366         count += deferredKeyframesRulesCountForList(*groupChildRules);
1367     }
1368
1369     return count;
1370 }
1371
1372 unsigned Internals::deferredKeyframesRulesCount(StyleSheet& styleSheet)
1373 {
1374     StyleSheetContents& contents = downcast<CSSStyleSheet>(styleSheet).contents();
1375     return deferredKeyframesRulesCountForList(contents.childRules());
1376 }
1377
1378 ExceptionOr<bool> Internals::isTimerThrottled(int timeoutId)
1379 {
1380     auto* timer = scriptExecutionContext()->findTimeout(timeoutId);
1381     if (!timer)
1382         return Exception { NotFoundError };
1383
1384     if (timer->intervalClampedToMinimum() > timer->m_originalInterval)
1385         return true;
1386
1387     return !!timer->alignedFireTime(MonotonicTime { });
1388 }
1389
1390 String Internals::requestAnimationFrameThrottlingReasons() const
1391 {
1392     auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
1393     if (!scriptedAnimationController)
1394         return String();
1395         
1396     TextStream ts;
1397     ts << scriptedAnimationController->throttlingReasons();
1398     return ts.release();
1399 }
1400
1401 double Internals::requestAnimationFrameInterval() const
1402 {
1403     auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
1404     if (!scriptedAnimationController)
1405         return INFINITY;
1406     return scriptedAnimationController->interval().value();
1407 }
1408
1409 bool Internals::scriptedAnimationsAreSuspended() const
1410 {
1411     Document* document = contextDocument();
1412     if (!document || !document->page())
1413         return true;
1414
1415     return document->page()->scriptedAnimationsSuspended();
1416 }
1417
1418 bool Internals::areTimersThrottled() const
1419 {
1420     return contextDocument()->isTimerThrottlingEnabled();
1421 }
1422
1423 void Internals::setEventThrottlingBehaviorOverride(Optional<EventThrottlingBehavior> value)
1424 {
1425     Document* document = contextDocument();
1426     if (!document || !document->page())
1427         return;
1428
1429     if (!value) {
1430         document->page()->setEventThrottlingBehaviorOverride(WTF::nullopt);
1431         return;
1432     }
1433
1434     switch (value.value()) {
1435     case Internals::EventThrottlingBehavior::Responsive:
1436         document->page()->setEventThrottlingBehaviorOverride(WebCore::EventThrottlingBehavior::Responsive);
1437         break;
1438     case Internals::EventThrottlingBehavior::Unresponsive:
1439         document->page()->setEventThrottlingBehaviorOverride(WebCore::EventThrottlingBehavior::Unresponsive);
1440         break;
1441     }
1442 }
1443
1444 Optional<Internals::EventThrottlingBehavior> Internals::eventThrottlingBehaviorOverride() const
1445 {
1446     Document* document = contextDocument();
1447     if (!document || !document->page())
1448         return WTF::nullopt;
1449
1450     auto behavior = document->page()->eventThrottlingBehaviorOverride();
1451     if (!behavior)
1452         return WTF::nullopt;
1453
1454     switch (behavior.value()) {
1455     case WebCore::EventThrottlingBehavior::Responsive:
1456         return Internals::EventThrottlingBehavior::Responsive;
1457     case WebCore::EventThrottlingBehavior::Unresponsive:
1458         return Internals::EventThrottlingBehavior::Unresponsive;
1459     }
1460
1461     return WTF::nullopt;
1462 }
1463
1464 String Internals::visiblePlaceholder(Element& element)
1465 {
1466     if (is<HTMLTextFormControlElement>(element)) {
1467         const HTMLTextFormControlElement& textFormControlElement = downcast<HTMLTextFormControlElement>(element);
1468         if (!textFormControlElement.isPlaceholderVisible())
1469             return String();
1470         if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
1471             return placeholderElement->textContent();
1472     }
1473
1474     return String();
1475 }
1476
1477 void Internals::setCanShowPlaceholder(Element& element, bool canShowPlaceholder)
1478 {
1479     if (is<HTMLTextFormControlElement>(element))
1480         downcast<HTMLTextFormControlElement>(element).setCanShowPlaceholder(canShowPlaceholder);
1481 }
1482
1483 Element* Internals::insertTextPlaceholder(int width, int height)
1484 {
1485     return frame()->editor().insertTextPlaceholder(IntSize { width, height }).get();
1486 }
1487
1488 void Internals::removeTextPlaceholder(Element& element)
1489 {
1490     if (is<TextPlaceholderElement>(element))
1491         frame()->editor().removeTextPlaceholder(downcast<TextPlaceholderElement>(element));
1492 }
1493
1494 void Internals::selectColorInColorChooser(HTMLInputElement& element, const String& colorValue)
1495 {
1496     element.selectColor(colorValue);
1497 }
1498
1499 ExceptionOr<Vector<String>> Internals::formControlStateOfPreviousHistoryItem()
1500 {
1501     HistoryItem* mainItem = frame()->loader().history().previousItem();
1502     if (!mainItem)
1503         return Exception { InvalidAccessError };
1504     String uniqueName = frame()->tree().uniqueName();
1505     if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName))
1506         return Exception { InvalidAccessError };
1507     return Vector<String> { mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState() };
1508 }
1509
1510 ExceptionOr<void> Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state)
1511 {
1512     HistoryItem* mainItem = frame()->loader().history().previousItem();
1513     if (!mainItem)
1514         return Exception { InvalidAccessError };
1515     String uniqueName = frame()->tree().uniqueName();
1516     if (mainItem->target() == uniqueName)
1517         mainItem->setDocumentState(state);
1518     else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
1519         subItem->setDocumentState(state);
1520     else
1521         return Exception { InvalidAccessError };
1522     return { };
1523 }
1524
1525 #if ENABLE(SPEECH_SYNTHESIS)
1526
1527 void Internals::enableMockSpeechSynthesizer()
1528 {
1529     Document* document = contextDocument();
1530     if (!document || !document->domWindow())
1531         return;
1532     SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(*document->domWindow());
1533     if (!synthesis)
1534         return;
1535
1536     synthesis->setPlatformSynthesizer(makeUnique<PlatformSpeechSynthesizerMock>(synthesis));
1537 }
1538
1539 #endif
1540
1541 #if ENABLE(WEB_RTC)
1542
1543 void Internals::emulateRTCPeerConnectionPlatformEvent(RTCPeerConnection& connection, const String& action)
1544 {
1545     if (!LibWebRTCProvider::webRTCAvailable())
1546         return;
1547
1548     connection.emulatePlatformEvent(action);
1549 }
1550
1551 void Internals::useMockRTCPeerConnectionFactory(const String& testCase)
1552 {
1553     if (!LibWebRTCProvider::webRTCAvailable())
1554         return;
1555
1556 #if USE(LIBWEBRTC)
1557     Document* document = contextDocument();
1558     LibWebRTCProvider* provider = (document && document->page()) ? &document->page()->libWebRTCProvider() : nullptr;
1559     WebCore::useMockRTCPeerConnectionFactory(provider, testCase);
1560 #else
1561     UNUSED_PARAM(testCase);
1562 #endif
1563 }
1564
1565 void Internals::setICECandidateFiltering(bool enabled)
1566 {
1567     auto* page = contextDocument()->page();
1568     if (!page)
1569         return;
1570
1571     auto& rtcController = page->rtcController();
1572     if (enabled)
1573         rtcController.enableICECandidateFiltering();
1574     else
1575         rtcController.disableICECandidateFilteringForAllOrigins();
1576 }
1577
1578 void Internals::setEnumeratingAllNetworkInterfacesEnabled(bool enabled)
1579 {
1580 #if USE(LIBWEBRTC)
1581     Document* document = contextDocument();
1582     auto* page = document->page();
1583     if (!page)
1584         return;
1585     auto& rtcProvider = page->libWebRTCProvider();
1586     if (enabled)
1587         rtcProvider.enableEnumeratingAllNetworkInterfaces();
1588     else
1589         rtcProvider.disableEnumeratingAllNetworkInterfaces();
1590 #else
1591     UNUSED_PARAM(enabled);
1592 #endif
1593 }
1594
1595 void Internals::stopPeerConnection(RTCPeerConnection& connection)
1596 {
1597     ActiveDOMObject& object = connection;
1598     object.stop();
1599 }
1600
1601 void Internals::clearPeerConnectionFactory()
1602 {
1603 #if USE(LIBWEBRTC)
1604     if (auto* page = contextDocument()->page())
1605         page->libWebRTCProvider().clearFactory();
1606 #endif
1607 }
1608
1609 void Internals::applyRotationForOutgoingVideoSources(RTCPeerConnection& connection)
1610 {
1611     connection.applyRotationForOutgoingVideoSources();
1612 }
1613
1614 void Internals::setEnableWebRTCEncryption(bool value)
1615 {
1616 #if USE(LIBWEBRTC)
1617     if (auto* page = contextDocument()->page())
1618         page->settings().setWebRTCEncryptionEnabled(value);
1619 #endif
1620 }
1621
1622 void Internals::setUseDTLS10(bool useDTLS10)
1623 {
1624 #if USE(LIBWEBRTC)
1625     auto* document = contextDocument();
1626     if (!document || !document->page())
1627         return;
1628     document->page()->libWebRTCProvider().setUseDTLS10(useDTLS10);
1629 #endif
1630 }
1631
1632 void Internals::setUseGPUProcessForWebRTC(bool useGPUProcess)
1633 {
1634 #if USE(LIBWEBRTC)
1635     auto* document = contextDocument();
1636     if (!document || !document->page())
1637         return;
1638
1639     document->page()->mediaRecorderProvider().setUseGPUProcess(useGPUProcess);
1640 #endif
1641 }
1642 #endif
1643
1644 #if ENABLE(MEDIA_STREAM)
1645 void Internals::setShouldInterruptAudioOnPageVisibilityChange(bool shouldInterrupt)
1646 {
1647     RuntimeEnabledFeatures::sharedFeatures().setInterruptAudioOnPageVisibilityChangeEnabled(shouldInterrupt);
1648 }
1649
1650 void Internals::setMediaCaptureRequiresSecureConnection(bool enabled)
1651 {
1652     Document* document = contextDocument();
1653     if (auto* page = document->page())
1654         page->settings().setMediaCaptureRequiresSecureConnection(enabled);
1655 }
1656
1657 static std::unique_ptr<MediaRecorderPrivate> createRecorderMockSource(MediaStreamPrivate& stream)
1658 {
1659     return std::unique_ptr<MediaRecorderPrivateMock>(new MediaRecorderPrivateMock(stream));
1660 }
1661
1662 void Internals::setCustomPrivateRecorderCreator()
1663 {
1664     WebCore::MediaRecorder::setCustomPrivateRecorderCreator(createRecorderMockSource);
1665 }
1666
1667 #endif
1668
1669 ExceptionOr<Ref<DOMRect>> Internals::absoluteCaretBounds()
1670 {
1671     Document* document = contextDocument();
1672     if (!document || !document->frame())
1673         return Exception { InvalidAccessError };
1674
1675     return DOMRect::create(document->frame()->selection().absoluteCaretBounds());
1676 }
1677     
1678 ExceptionOr<bool> Internals::isCaretBlinkingSuspended()
1679 {
1680     Document* document = contextDocument();
1681     if (!document || !document->frame())
1682         return Exception { InvalidAccessError };
1683     
1684     return document->frame()->selection().isCaretBlinkingSuspended();
1685 }
1686
1687 Ref<DOMRect> Internals::boundingBox(Element& element)
1688 {
1689     element.document().updateLayoutIgnorePendingStylesheets();
1690     auto renderer = element.renderer();
1691     if (!renderer)
1692         return DOMRect::create();
1693     return DOMRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
1694 }
1695
1696 ExceptionOr<Ref<DOMRectList>> Internals::inspectorHighlightRects()
1697 {
1698     Document* document = contextDocument();
1699     if (!document || !document->page())
1700         return Exception { InvalidAccessError };
1701
1702     Highlight highlight;
1703     document->page()->inspectorController().getHighlight(highlight, InspectorOverlay::CoordinateSystem::View);
1704     return DOMRectList::create(highlight.quads);
1705 }
1706
1707 ExceptionOr<unsigned> Internals::markerCountForNode(Node& node, const String& markerType)
1708 {
1709     OptionSet<DocumentMarker::MarkerType> markerTypes;
1710     if (!markerTypesFrom(markerType, markerTypes))
1711         return Exception { SyntaxError };
1712
1713     node.document().frame()->editor().updateEditorUINowIfScheduled();
1714     return node.document().markers().markersFor(node, markerTypes).size();
1715 }
1716
1717 ExceptionOr<RenderedDocumentMarker*> Internals::markerAt(Node& node, const String& markerType, unsigned index)
1718 {
1719     node.document().updateLayoutIgnorePendingStylesheets();
1720
1721     OptionSet<DocumentMarker::MarkerType> markerTypes;
1722     if (!markerTypesFrom(markerType, markerTypes))
1723         return Exception { SyntaxError };
1724
1725     node.document().frame()->editor().updateEditorUINowIfScheduled();
1726
1727     Vector<RenderedDocumentMarker*> markers = node.document().markers().markersFor(node, markerTypes);
1728     if (markers.size() <= index)
1729         return nullptr;
1730     return markers[index];
1731 }
1732
1733 ExceptionOr<RefPtr<Range>> Internals::markerRangeForNode(Node& node, const String& markerType, unsigned index)
1734 {
1735     auto result = markerAt(node, markerType, index);
1736     if (result.hasException())
1737         return result.releaseException();
1738     auto marker = result.releaseReturnValue();
1739     if (!marker)
1740         return nullptr;
1741     return RefPtr<Range> { Range::create(node.document(), &node, marker->startOffset(), &node, marker->endOffset()) };
1742 }
1743
1744 ExceptionOr<String> Internals::markerDescriptionForNode(Node& node, const String& markerType, unsigned index)
1745 {
1746     auto result = markerAt(node, markerType, index);
1747     if (result.hasException())
1748         return result.releaseException();
1749     auto marker = result.releaseReturnValue();
1750     if (!marker)
1751         return String();
1752     return String { marker->description() };
1753 }
1754
1755 ExceptionOr<String> Internals::dumpMarkerRects(const String& markerTypeString)
1756 {
1757     DocumentMarker::MarkerType markerType;
1758     if (!markerTypeFrom(markerTypeString, markerType))
1759         return Exception { SyntaxError };
1760
1761     contextDocument()->markers().updateRectsForInvalidatedMarkersOfType(markerType);
1762     auto rects = contextDocument()->markers().renderedRectsForMarkers(markerType);
1763
1764     // FIXME: Using fixed precision here for width because of test results that contain numbers with specific precision. Would be nice to update the test results and move to default formatting.
1765     StringBuilder rectString;
1766     rectString.appendLiteral("marker rects: ");
1767     for (const auto& rect : rects)
1768         rectString.append('(', rect.x(), ", ", rect.y(), ", ", FormattedNumber::fixedPrecision(rect.width()), ", ", rect.height(), ") ");
1769     return rectString.toString();
1770 }
1771
1772 ExceptionOr<void> Internals::setMarkedTextMatchesAreHighlighted(bool flag)
1773 {
1774     Document* document = contextDocument();
1775     if (!document || !document->frame())
1776         return Exception { InvalidAccessError };
1777     document->frame()->editor().setMarkedTextMatchesAreHighlighted(flag);
1778     return { };
1779 }
1780
1781 void Internals::invalidateFontCache()
1782 {
1783     FontCache::singleton().invalidate();
1784 }
1785
1786 void Internals::setFontSmoothingEnabled(bool enabled)
1787 {
1788     FontCascade::setShouldUseSmoothing(enabled);
1789 }
1790
1791 ExceptionOr<void> Internals::setLowPowerModeEnabled(bool isEnabled)
1792 {
1793     auto* document = contextDocument();
1794     if (!document)
1795         return Exception { InvalidAccessError };
1796     auto* page = document->page();
1797     if (!page)
1798         return Exception { InvalidAccessError };
1799
1800     page->setLowPowerModeEnabledOverrideForTesting(isEnabled);
1801     return { };
1802 }
1803
1804 ExceptionOr<void> Internals::setScrollViewPosition(int x, int y)
1805 {
1806     Document* document = contextDocument();
1807     if (!document || !document->view())
1808         return Exception { InvalidAccessError };
1809
1810     auto& frameView = *document->view();
1811     bool constrainsScrollingToContentEdgeOldValue = frameView.constrainsScrollingToContentEdge();
1812     bool scrollbarsSuppressedOldValue = frameView.scrollbarsSuppressed();
1813
1814     frameView.setConstrainsScrollingToContentEdge(false);
1815     frameView.setScrollbarsSuppressed(false);
1816     frameView.setScrollOffsetFromInternals({ x, y });
1817     frameView.setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
1818     frameView.setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
1819
1820     return { };
1821 }
1822
1823 ExceptionOr<void> Internals::unconstrainedScrollTo(Element& element, double x, double y)
1824 {
1825     Document* document = contextDocument();
1826     if (!document || !document->view())
1827         return Exception { InvalidAccessError };
1828
1829     element.scrollTo(ScrollToOptions(x, y), ScrollClamping::Unclamped);
1830
1831     auto& frameView = *document->view();
1832     frameView.setViewportConstrainedObjectsNeedLayout();
1833
1834     return { };
1835 }
1836
1837 ExceptionOr<Ref<DOMRect>> Internals::layoutViewportRect()
1838 {
1839     Document* document = contextDocument();
1840     if (!document || !document->frame())
1841         return Exception { InvalidAccessError };
1842
1843     document->updateLayoutIgnorePendingStylesheets();
1844
1845     auto& frameView = *document->view();
1846     return DOMRect::create(frameView.layoutViewportRect());
1847 }
1848
1849 ExceptionOr<Ref<DOMRect>> Internals::visualViewportRect()
1850 {
1851     Document* document = contextDocument();
1852     if (!document || !document->frame())
1853         return Exception { InvalidAccessError };
1854
1855     document->updateLayoutIgnorePendingStylesheets();
1856
1857     auto& frameView = *document->view();
1858     return DOMRect::create(frameView.visualViewportRect());
1859 }
1860
1861 ExceptionOr<void> Internals::setViewIsTransparent(bool transparent)
1862 {
1863     Document* document = contextDocument();
1864     if (!document || !document->view())
1865         return Exception { InvalidAccessError };
1866     Optional<Color> backgroundColor;
1867     if (transparent)
1868         backgroundColor = Color(Color::transparent);
1869     document->view()->updateBackgroundRecursively(backgroundColor);
1870     return { };
1871 }
1872
1873 ExceptionOr<String> Internals::viewBaseBackgroundColor()
1874 {
1875     Document* document = contextDocument();
1876     if (!document || !document->view())
1877         return Exception { InvalidAccessError };
1878     return document->view()->baseBackgroundColor().cssText();
1879 }
1880
1881 ExceptionOr<void> Internals::setViewBaseBackgroundColor(const String& colorValue)
1882 {
1883     Document* document = contextDocument();
1884     if (!document || !document->view())
1885         return Exception { InvalidAccessError };
1886
1887     if (colorValue == "transparent") {
1888         document->view()->setBaseBackgroundColor(Color::transparent);
1889         return { };
1890     }
1891     if (colorValue == "white") {
1892         document->view()->setBaseBackgroundColor(Color::white);
1893         return { };
1894     }
1895     return Exception { SyntaxError };
1896 }
1897
1898 ExceptionOr<void> Internals::setPagination(const String& mode, int gap, int pageLength)
1899 {
1900     Document* document = contextDocument();
1901     if (!document || !document->page())
1902         return Exception { InvalidAccessError };
1903
1904     Pagination pagination;
1905     if (mode == "Unpaginated")
1906         pagination.mode = Pagination::Unpaginated;
1907     else if (mode == "LeftToRightPaginated")
1908         pagination.mode = Pagination::LeftToRightPaginated;
1909     else if (mode == "RightToLeftPaginated")
1910         pagination.mode = Pagination::RightToLeftPaginated;
1911     else if (mode == "TopToBottomPaginated")
1912         pagination.mode = Pagination::TopToBottomPaginated;
1913     else if (mode == "BottomToTopPaginated")
1914         pagination.mode = Pagination::BottomToTopPaginated;
1915     else
1916         return Exception { SyntaxError };
1917
1918     pagination.gap = gap;
1919     pagination.pageLength = pageLength;
1920     document->page()->setPagination(pagination);
1921
1922     return { };
1923 }
1924
1925 ExceptionOr<void> Internals::setPaginationLineGridEnabled(bool enabled)
1926 {
1927     Document* document = contextDocument();
1928     if (!document || !document->page())
1929         return Exception { InvalidAccessError };
1930     document->page()->setPaginationLineGridEnabled(enabled);
1931     return { };
1932 }
1933
1934 ExceptionOr<String> Internals::configurationForViewport(float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight)
1935 {
1936     Document* document = contextDocument();
1937     if (!document || !document->page())
1938         return Exception { InvalidAccessError };
1939
1940     const int defaultLayoutWidthForNonMobilePages = 980;
1941
1942     ViewportArguments arguments = document->page()->viewportArguments();
1943     ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
1944     restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
1945     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
1946
1947     // FIXME: Using fixed precision here because of test results that contain numbers with specific precision. Would be nice to update the test results and move to default formatting.
1948     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"));
1949 }
1950
1951 ExceptionOr<bool> Internals::wasLastChangeUserEdit(Element& textField)
1952 {
1953     if (is<HTMLInputElement>(textField))
1954         return downcast<HTMLInputElement>(textField).lastChangeWasUserEdit();
1955
1956     if (is<HTMLTextAreaElement>(textField))
1957         return downcast<HTMLTextAreaElement>(textField).lastChangeWasUserEdit();
1958
1959     return Exception { InvalidNodeTypeError };
1960 }
1961
1962 bool Internals::elementShouldAutoComplete(HTMLInputElement& element)
1963 {
1964     return element.shouldAutocomplete();
1965 }
1966
1967 void Internals::setAutofilled(HTMLInputElement& element, bool enabled)
1968 {
1969     element.setAutoFilled(enabled);
1970 }
1971
1972 void Internals::setAutoFilledAndViewable(HTMLInputElement& element, bool enabled)
1973 {
1974     element.setAutoFilledAndViewable(enabled);
1975 }
1976
1977 static AutoFillButtonType toAutoFillButtonType(Internals::AutoFillButtonType type)
1978 {
1979     switch (type) {
1980     case Internals::AutoFillButtonType::None:
1981         return AutoFillButtonType::None;
1982     case Internals::AutoFillButtonType::Credentials:
1983         return AutoFillButtonType::Credentials;
1984     case Internals::AutoFillButtonType::Contacts:
1985         return AutoFillButtonType::Contacts;
1986     case Internals::AutoFillButtonType::StrongPassword:
1987         return AutoFillButtonType::StrongPassword;
1988     case Internals::AutoFillButtonType::CreditCard:
1989         return AutoFillButtonType::CreditCard;
1990     }
1991     ASSERT_NOT_REACHED();
1992     return AutoFillButtonType::None;
1993 }
1994
1995 static Internals::AutoFillButtonType toInternalsAutoFillButtonType(AutoFillButtonType type)
1996 {
1997     switch (type) {
1998     case AutoFillButtonType::None:
1999         return Internals::AutoFillButtonType::None;
2000     case AutoFillButtonType::Credentials:
2001         return Internals::AutoFillButtonType::Credentials;
2002     case AutoFillButtonType::Contacts:
2003         return Internals::AutoFillButtonType::Contacts;
2004     case AutoFillButtonType::StrongPassword:
2005         return Internals::AutoFillButtonType::StrongPassword;
2006     case AutoFillButtonType::CreditCard:
2007         return Internals::AutoFillButtonType::CreditCard;
2008     }
2009     ASSERT_NOT_REACHED();
2010     return Internals::AutoFillButtonType::None;
2011 }
2012
2013 void Internals::setShowAutoFillButton(HTMLInputElement& element, AutoFillButtonType type)
2014 {
2015     element.setShowAutoFillButton(toAutoFillButtonType(type));
2016 }
2017
2018 auto Internals::autoFillButtonType(const HTMLInputElement& element) -> AutoFillButtonType
2019 {
2020     return toInternalsAutoFillButtonType(element.autoFillButtonType());
2021 }
2022
2023 auto Internals::lastAutoFillButtonType(const HTMLInputElement& element) -> AutoFillButtonType
2024 {
2025     return toInternalsAutoFillButtonType(element.lastAutoFillButtonType());
2026 }
2027
2028 ExceptionOr<void> Internals::scrollElementToRect(Element& element, int x, int y, int w, int h)
2029 {
2030     FrameView* frameView = element.document().view();
2031     if (!frameView)
2032         return Exception { InvalidAccessError };
2033     frameView->scrollElementToRect(element, { x, y, w, h });
2034     return { };
2035 }
2036
2037 ExceptionOr<String> Internals::autofillFieldName(Element& element)
2038 {
2039     if (!is<HTMLFormControlElement>(element))
2040         return Exception { InvalidNodeTypeError };
2041
2042     return String { downcast<HTMLFormControlElement>(element).autofillData().fieldName };
2043 }
2044
2045 ExceptionOr<void> Internals::invalidateControlTints()
2046 {
2047     Document* document = contextDocument();
2048     if (!document || !document->view())
2049         return Exception { InvalidAccessError };
2050
2051     document->view()->invalidateControlTints();
2052     return { };
2053 }
2054
2055 RefPtr<Range> Internals::rangeFromLocationAndLength(Element& scope, unsigned rangeLocation, unsigned rangeLength)
2056 {
2057     return createLiveRange(resolveCharacterRange(makeRangeSelectingNodeContents(scope), { rangeLocation, rangeLength }));
2058 }
2059
2060 unsigned Internals::locationFromRange(Element& scope, const Range& range)
2061 {
2062     return clampTo<unsigned>(characterRange(makeBoundaryPointBeforeNodeContents(scope), range).location);
2063 }
2064
2065 unsigned Internals::lengthFromRange(Element& scope, const Range& range)
2066 {
2067     return clampTo<unsigned>(characterRange(makeBoundaryPointBeforeNodeContents(scope), range).length);
2068 }
2069
2070 String Internals::rangeAsText(const Range& range)
2071 {
2072     return range.text();
2073 }
2074
2075 String Internals::rangeAsTextUsingBackwardsTextIterator(const Range& range)
2076 {
2077     String result;
2078     for (SimplifiedBackwardsTextIterator backwardsIterator(range); !backwardsIterator.atEnd(); backwardsIterator.advance())
2079         result.insert(backwardsIterator.text().toString(), 0);
2080     return result;
2081 }
2082
2083 Ref<Range> Internals::subrange(Range& range, unsigned rangeLocation, unsigned rangeLength)
2084 {
2085     return createLiveRange(resolveCharacterRange(range, { rangeLocation, rangeLength }));
2086 }
2087
2088 RefPtr<Range> Internals::rangeOfStringNearLocation(const Range& searchRange, const String& text, unsigned targetOffset)
2089 {
2090     return createLiveRange(findClosestPlainText(searchRange, text, { }, targetOffset));
2091 }
2092
2093 #if !PLATFORM(MAC)
2094 ExceptionOr<RefPtr<Range>> Internals::rangeForDictionaryLookupAtLocation(int, int)
2095 {
2096     return Exception { InvalidAccessError };
2097 }
2098 #endif
2099
2100 ExceptionOr<void> Internals::setDelegatesScrolling(bool enabled)
2101 {
2102     Document* document = contextDocument();
2103     // Delegate scrolling is valid only on mainframe's view.
2104     if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame())
2105         return Exception { InvalidAccessError };
2106
2107     document->view()->setDelegatesScrolling(enabled);
2108     return { };
2109 }
2110
2111 ExceptionOr<uint64_t> Internals::lastSpellCheckRequestSequence()
2112 {
2113     Document* document = contextDocument();
2114     if (!document || !document->frame())
2115         return Exception { InvalidAccessError };
2116
2117     return document->frame()->editor().spellChecker().lastRequestIdentifier().toUInt64();
2118 }
2119
2120 ExceptionOr<uint64_t> Internals::lastSpellCheckProcessedSequence()
2121 {
2122     Document* document = contextDocument();
2123     if (!document || !document->frame())
2124         return Exception { InvalidAccessError };
2125
2126     return document->frame()->editor().spellChecker().lastProcessedIdentifier().toUInt64();
2127 }
2128
2129 Vector<String> Internals::userPreferredLanguages() const
2130 {
2131     return WTF::userPreferredLanguages();
2132 }
2133
2134 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
2135 {
2136     overrideUserPreferredLanguages(languages);
2137 }
2138
2139 Vector<String> Internals::userPreferredAudioCharacteristics() const
2140 {
2141     Document* document = contextDocument();
2142     if (!document || !document->page())
2143         return Vector<String>();
2144 #if ENABLE(VIDEO_TRACK)
2145     return document->page()->group().captionPreferences().preferredAudioCharacteristics();
2146 #else
2147     return Vector<String>();
2148 #endif
2149 }
2150
2151 void Internals::setUserPreferredAudioCharacteristic(const String& characteristic)
2152 {
2153     Document* document = contextDocument();
2154     if (!document || !document->page())
2155         return;
2156 #if ENABLE(VIDEO_TRACK)
2157     document->page()->group().captionPreferences().setPreferredAudioCharacteristic(characteristic);
2158 #else
2159     UNUSED_PARAM(characteristic);
2160 #endif
2161 }
2162
2163 ExceptionOr<unsigned> Internals::wheelEventHandlerCount()
2164 {
2165     Document* document = contextDocument();
2166     if (!document)
2167         return Exception { InvalidAccessError };
2168
2169     return document->wheelEventHandlerCount();
2170 }
2171
2172 ExceptionOr<unsigned> Internals::touchEventHandlerCount()
2173 {
2174     Document* document = contextDocument();
2175     if (!document)
2176         return Exception { InvalidAccessError };
2177
2178     return document->touchEventHandlerCount();
2179 }
2180
2181 ExceptionOr<Ref<DOMRectList>> Internals::touchEventRectsForEvent(const String& eventName)
2182 {
2183     Document* document = contextDocument();
2184     if (!document || !document->page())
2185         return Exception { InvalidAccessError };
2186
2187     return document->page()->touchEventRectsForEventForTesting(eventName);
2188 }
2189
2190 ExceptionOr<Ref<DOMRectList>> Internals::passiveTouchEventListenerRects()
2191 {
2192     Document* document = contextDocument();
2193     if (!document || !document->page())
2194         return Exception { InvalidAccessError };
2195
2196     return document->page()->passiveTouchEventListenerRectsForTesting();
2197 }
2198
2199 // FIXME: Remove the document argument. It is almost always the same as
2200 // contextDocument(), with the exception of a few tests that pass a
2201 // different document, and could just make the call through another Internals
2202 // instance instead.
2203 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
2204 {
2205     if (!document.frame() || !document.frame()->view())
2206         return Exception { InvalidAccessError };
2207
2208     Frame* frame = document.frame();
2209     FrameView* frameView = document.view();
2210     RenderView* renderView = document.renderView();
2211     if (!renderView)
2212         return nullptr;
2213
2214     document.updateLayoutIgnorePendingStylesheets();
2215
2216     float zoomFactor = frame->pageZoomFactor();
2217     LayoutPoint point(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY());
2218
2219     OptionSet<HitTestRequest::RequestType> hitType { HitTestRequest::ReadOnly, HitTestRequest::Active, HitTestRequest::CollectMultipleElements };
2220     if (ignoreClipping)
2221         hitType.add(HitTestRequest::IgnoreClipping);
2222     if (!allowUserAgentShadowContent)
2223         hitType.add(HitTestRequest::DisallowUserAgentShadowContent);
2224     if (allowChildFrameContent)
2225         hitType.add(HitTestRequest::AllowChildFrameContent);
2226
2227     HitTestRequest request(hitType);
2228
2229     // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
2230     if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
2231         return nullptr;
2232
2233     HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
2234     document.hitTest(request, result);
2235     auto matches = WTF::map(result.listBasedTestResult(), [](const auto& node) { return node.copyRef(); });
2236     return RefPtr<NodeList> { StaticNodeList::create(WTFMove(matches)) };
2237 }
2238
2239 class GetCallerCodeBlockFunctor {
2240 public:
2241     GetCallerCodeBlockFunctor()
2242         : m_iterations(0)
2243         , m_codeBlock(0)
2244     {
2245     }
2246
2247     StackVisitor::Status operator()(StackVisitor& visitor) const
2248     {
2249         ++m_iterations;
2250         if (m_iterations < 2)
2251             return StackVisitor::Continue;
2252
2253         m_codeBlock = visitor->codeBlock();
2254         return StackVisitor::Done;
2255     }
2256
2257     CodeBlock* codeBlock() const { return m_codeBlock; }
2258
2259 private:
2260     mutable int m_iterations;
2261     mutable CodeBlock* m_codeBlock;
2262 };
2263
2264 String Internals::parserMetaData(JSC::JSValue code)
2265 {
2266     JSC::VM& vm = contextDocument()->vm();
2267     JSC::CallFrame* callFrame = vm.topCallFrame;
2268     JSC::JSGlobalObject* globalObject = callFrame->lexicalGlobalObject(vm);
2269     ScriptExecutable* executable;
2270
2271     if (!code || code.isNull() || code.isUndefined()) {
2272         GetCallerCodeBlockFunctor iter;
2273         callFrame->iterate(vm, iter);
2274         CodeBlock* codeBlock = iter.codeBlock();
2275         executable = codeBlock->ownerExecutable();
2276     } else if (code.isCallable(vm)) {
2277         JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(globalObject));
2278         executable = funcObj->jsExecutable();
2279     } else
2280         return String();
2281
2282     unsigned startLine = executable->firstLine();
2283     unsigned startColumn = executable->startColumn();
2284     unsigned endLine = executable->lastLine();
2285     unsigned endColumn = executable->endColumn();
2286
2287     StringBuilder result;
2288
2289     if (executable->isFunctionExecutable()) {
2290         FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable);
2291         String inferredName = funcExecutable->ecmaName().string();
2292         result.appendLiteral("function \"");
2293         result.append(inferredName);
2294         result.append('"');
2295     } else if (executable->isEvalExecutable())
2296         result.appendLiteral("eval");
2297     else if (executable->isModuleProgramExecutable())
2298         result.appendLiteral("module");
2299     else if (executable->isProgramExecutable())
2300         result.appendLiteral("program");
2301     else
2302         ASSERT_NOT_REACHED();
2303
2304     result.appendLiteral(" { ");
2305     result.appendNumber(startLine);
2306     result.append(':');
2307     result.appendNumber(startColumn);
2308     result.appendLiteral(" - ");
2309     result.appendNumber(endLine);
2310     result.append(':');
2311     result.appendNumber(endColumn);
2312     result.appendLiteral(" }");
2313
2314     return result.toString();
2315 }
2316
2317 void Internals::updateEditorUINowIfScheduled()
2318 {
2319     if (Document* document = contextDocument()) {
2320         if (Frame* frame = document->frame())
2321             frame->editor().updateEditorUINowIfScheduled();
2322     }
2323 }
2324
2325 bool Internals::hasSpellingMarker(int from, int length)
2326 {
2327     Document* document = contextDocument();
2328     if (!document || !document->frame())
2329         return false;
2330
2331     updateEditorUINowIfScheduled();
2332
2333     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
2334 }
2335
2336 bool Internals::hasAutocorrectedMarker(int from, int length)
2337 {
2338     Document* document = contextDocument();
2339     if (!document || !document->frame())
2340         return false;
2341
2342     updateEditorUINowIfScheduled();
2343
2344     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
2345 }
2346
2347 void Internals::setContinuousSpellCheckingEnabled(bool enabled)
2348 {
2349     if (!contextDocument() || !contextDocument()->frame())
2350         return;
2351
2352     if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
2353         contextDocument()->frame()->editor().toggleContinuousSpellChecking();
2354 }
2355
2356 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled)
2357 {
2358     if (!contextDocument() || !contextDocument()->frame())
2359         return;
2360
2361 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2362     if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
2363         contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
2364 #else
2365     UNUSED_PARAM(enabled);
2366 #endif
2367 }
2368
2369 void Internals::setAutomaticLinkDetectionEnabled(bool enabled)
2370 {
2371     if (!contextDocument() || !contextDocument()->frame())
2372         return;
2373
2374 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2375     if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
2376         contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
2377 #else
2378     UNUSED_PARAM(enabled);
2379 #endif
2380 }
2381
2382 bool Internals::testProcessIncomingSyncMessagesWhenWaitingForSyncReply()
2383 {
2384     ASSERT(contextDocument());
2385     ASSERT(contextDocument()->page());
2386     return contextDocument()->page()->chrome().client().testProcessIncomingSyncMessagesWhenWaitingForSyncReply();
2387 }
2388
2389 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled)
2390 {
2391     if (!contextDocument() || !contextDocument()->frame())
2392         return;
2393
2394 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2395     if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
2396         contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
2397 #else
2398     UNUSED_PARAM(enabled);
2399 #endif
2400 }
2401
2402 void Internals::setAutomaticTextReplacementEnabled(bool enabled)
2403 {
2404     if (!contextDocument() || !contextDocument()->frame())
2405         return;
2406
2407 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2408     if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
2409         contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
2410 #else
2411     UNUSED_PARAM(enabled);
2412 #endif
2413 }
2414
2415 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled)
2416 {
2417     if (!contextDocument() || !contextDocument()->frame())
2418         return;
2419
2420 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
2421     if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
2422         contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
2423 #else
2424     UNUSED_PARAM(enabled);
2425 #endif
2426 }
2427
2428 void Internals::handleAcceptedCandidate(const String& candidate, unsigned location, unsigned length)
2429 {
2430     if (!contextDocument() || !contextDocument()->frame())
2431         return;
2432
2433     TextCheckingResult result;
2434     result.type = TextCheckingType::None;
2435     result.range = { location, length };
2436     result.replacement = candidate;
2437     contextDocument()->frame()->editor().handleAcceptedCandidate(result);
2438 }
2439
2440 void Internals::changeSelectionListType()
2441 {
2442     if (auto frame = makeRefPtr(this->frame()))
2443         frame->editor().changeSelectionListType();
2444 }
2445
2446 bool Internals::isOverwriteModeEnabled()
2447 {
2448     Document* document = contextDocument();
2449     if (!document || !document->frame())
2450         return false;
2451
2452     return document->frame()->editor().isOverwriteModeEnabled();
2453 }
2454
2455 void Internals::toggleOverwriteModeEnabled()
2456 {
2457     Document* document = contextDocument();
2458     if (!document || !document->frame())
2459         return;
2460
2461     document->frame()->editor().toggleOverwriteModeEnabled();
2462 }
2463
2464 static ExceptionOr<FindOptions> parseFindOptions(const Vector<String>& optionList)
2465 {
2466     const struct {
2467         const char* name;
2468         FindOptionFlag value;
2469     } flagList[] = {
2470         {"CaseInsensitive", CaseInsensitive},
2471         {"AtWordStarts", AtWordStarts},
2472         {"TreatMedialCapitalAsWordStart", TreatMedialCapitalAsWordStart},
2473         {"Backwards", Backwards},
2474         {"WrapAround", WrapAround},
2475         {"StartInSelection", StartInSelection},
2476         {"DoNotRevealSelection", DoNotRevealSelection},
2477         {"AtWordEnds", AtWordEnds},
2478         {"DoNotTraverseFlatTree", DoNotTraverseFlatTree},
2479     };
2480     FindOptions result;
2481     for (auto& option : optionList) {
2482         bool found = false;
2483         for (auto& flag : flagList) {
2484             if (flag.name == option) {
2485                 result.add(flag.value);
2486                 found = true;
2487                 break;
2488             }
2489         }
2490         if (!found)
2491             return Exception { SyntaxError };
2492     }
2493     return result;
2494 }
2495
2496 ExceptionOr<RefPtr<Range>> Internals::rangeOfString(const String& text, RefPtr<Range>&& referenceRange, const Vector<String>& findOptions)
2497 {
2498     Document* document = contextDocument();
2499     if (!document || !document->frame())
2500         return Exception { InvalidAccessError };
2501
2502     auto parsedOptions = parseFindOptions(findOptions);
2503     if (parsedOptions.hasException())
2504         return parsedOptions.releaseException();
2505
2506     return document->frame()->editor().rangeOfString(text, referenceRange.get(), parsedOptions.releaseReturnValue());
2507 }
2508
2509 ExceptionOr<unsigned> Internals::countMatchesForText(const String& text, const Vector<String>& findOptions, const String& markMatches)
2510 {
2511     Document* document = contextDocument();
2512     if (!document || !document->frame())
2513         return Exception { InvalidAccessError };
2514
2515     auto parsedOptions = parseFindOptions(findOptions);
2516     if (parsedOptions.hasException())
2517         return parsedOptions.releaseException();
2518
2519     bool mark = markMatches == "mark";
2520     return document->frame()->editor().countMatchesForText(text, nullptr, parsedOptions.releaseReturnValue(), 1000, mark, nullptr);
2521 }
2522
2523 ExceptionOr<unsigned> Internals::countFindMatches(const String& text, const Vector<String>& findOptions)
2524 {
2525     Document* document = contextDocument();
2526     if (!document || !document->page())
2527         return Exception { InvalidAccessError };
2528
2529     auto parsedOptions = parseFindOptions(findOptions);
2530     if (parsedOptions.hasException())
2531         return parsedOptions.releaseException();
2532
2533     return document->page()->countFindMatches(text, parsedOptions.releaseReturnValue(), 1000);
2534 }
2535
2536 #if ENABLE(INDEXED_DATABASE)
2537 unsigned Internals::numberOfIDBTransactions() const
2538 {
2539     return IDBTransaction::numberOfIDBTransactions;
2540 }
2541 #endif
2542
2543 unsigned Internals::numberOfLiveNodes() const
2544 {
2545     unsigned nodeCount = 0;
2546     for (auto* document : Document::allDocuments())
2547         nodeCount += document->referencingNodeCount();
2548     return nodeCount;
2549 }
2550
2551 unsigned Internals::numberOfLiveDocuments() const
2552 {
2553     return Document::allDocuments().size();
2554 }
2555
2556 unsigned Internals::referencingNodeCount(const Document& document) const
2557 {
2558     return document.referencingNodeCount();
2559 }
2560
2561 #if ENABLE(INTERSECTION_OBSERVER)
2562 unsigned Internals::numberOfIntersectionObservers(const Document& document) const
2563 {
2564     return document.numberOfIntersectionObservers();
2565 }
2566 #endif
2567
2568 uint64_t Internals::documentIdentifier(const Document& document) const
2569 {
2570     return document.identifier().toUInt64();
2571 }
2572
2573 bool Internals::isDocumentAlive(uint64_t documentIdentifier) const
2574 {
2575     return Document::allDocumentsMap().contains(makeObjectIdentifier<DocumentIdentifierType>(documentIdentifier));
2576 }
2577
2578 uint64_t Internals::storageAreaMapCount() const
2579 {
2580     auto* page = contextDocument() ? contextDocument()->page() : nullptr;
2581     if (!page)
2582         return 0;
2583
2584     return page->storageNamespaceProvider().localStorageNamespace(page->sessionID()).storageAreaMapCountForTesting();
2585 }
2586
2587 uint64_t Internals::elementIdentifier(Element& element) const
2588 {
2589     return element.document().identifierForElement(element).toUInt64();
2590 }
2591
2592 uint64_t Internals::frameIdentifier(const Document& document) const
2593 {
2594     if (auto* page = document.page())
2595         return page->mainFrame().loader().frameID().valueOr(FrameIdentifier { }).toUInt64();
2596     return 0;
2597 }
2598
2599 uint64_t Internals::pageIdentifier(const Document& document) const
2600 {
2601     return document.pageID().valueOr(PageIdentifier { }).toUInt64();
2602 }
2603
2604 bool Internals::isAnyWorkletGlobalScopeAlive() const
2605 {
2606 #if ENABLE(CSS_PAINTING_API)
2607     return !WorkletGlobalScope::allWorkletGlobalScopesSet().isEmpty();
2608 #else
2609     return false;
2610 #endif
2611 }
2612
2613 String Internals::serviceWorkerClientIdentifier(const Document& document) const
2614 {
2615 #if ENABLE(SERVICE_WORKER)
2616     return ServiceWorkerClientIdentifier { ServiceWorkerProvider::singleton().serviceWorkerConnection().serverConnectionIdentifier(), document.identifier() }.toString();
2617 #else
2618     UNUSED_PARAM(document);
2619     return String();
2620 #endif
2621 }
2622
2623 RefPtr<WindowProxy> Internals::openDummyInspectorFrontend(const String& url)
2624 {
2625     auto* inspectedPage = contextDocument()->frame()->page();
2626     auto* window = inspectedPage->mainFrame().document()->domWindow();
2627     auto frontendWindowProxy = window->open(*window, *window, url, "", "").releaseReturnValue();
2628     m_inspectorFrontend = makeUnique<InspectorStubFrontend>(*inspectedPage, downcast<DOMWindow>(frontendWindowProxy->window()));
2629     return frontendWindowProxy;
2630 }
2631
2632 void Internals::closeDummyInspectorFrontend()
2633 {
2634     m_inspectorFrontend = nullptr;
2635 }
2636
2637 ExceptionOr<void> Internals::setInspectorIsUnderTest(bool isUnderTest)
2638 {
2639     Page* page = contextDocument()->frame()->page();
2640     if (!page)
2641         return Exception { InvalidAccessError };
2642
2643     page->inspectorController().setIsUnderTest(isUnderTest);
2644     return { };
2645 }
2646
2647 bool Internals::hasGrammarMarker(int from, int length)
2648 {
2649     Document* document = contextDocument();
2650     if (!document || !document->frame())
2651         return false;
2652
2653     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
2654 }
2655
2656 unsigned Internals::numberOfScrollableAreas()
2657 {
2658     Document* document = contextDocument();
2659     if (!document || !document->frame())
2660         return 0;
2661
2662     unsigned count = 0;
2663     Frame* frame = document->frame();
2664     if (frame->view()->scrollableAreas())
2665         count += frame->view()->scrollableAreas()->size();
2666
2667     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
2668         if (child->view() && child->view()->scrollableAreas())
2669             count += child->view()->scrollableAreas()->size();
2670     }
2671
2672     return count;
2673 }
2674
2675 ExceptionOr<bool> Internals::isPageBoxVisible(int pageNumber)
2676 {
2677     Document* document = contextDocument();
2678     if (!document)
2679         return Exception { InvalidAccessError };
2680
2681     return document->isPageBoxVisible(pageNumber);
2682 }
2683
2684 static LayerTreeFlags toLayerTreeFlags(unsigned short flags)
2685 {
2686     LayerTreeFlags layerTreeFlags = 0;
2687     if (flags & Internals::LAYER_TREE_INCLUDES_VISIBLE_RECTS)
2688         layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
2689     if (flags & Internals::LAYER_TREE_INCLUDES_TILE_CACHES)
2690         layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
2691     if (flags & Internals::LAYER_TREE_INCLUDES_REPAINT_RECTS)
2692         layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
2693     if (flags & Internals::LAYER_TREE_INCLUDES_PAINTING_PHASES)
2694         layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
2695     if (flags & Internals::LAYER_TREE_INCLUDES_CONTENT_LAYERS)
2696         layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
2697     if (flags & Internals::LAYER_TREE_INCLUDES_ACCELERATES_DRAWING)
2698         layerTreeFlags |= LayerTreeFlagsIncludeAcceleratesDrawing;
2699     if (flags & Internals::LAYER_TREE_INCLUDES_CLIPPING)
2700         layerTreeFlags |= LayerTreeFlagsIncludeClipping;
2701     if (flags & Internals::LAYER_TREE_INCLUDES_BACKING_STORE_ATTACHED)
2702         layerTreeFlags |= LayerTreeFlagsIncludeBackingStoreAttached;
2703     if (flags & Internals::LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES)
2704         layerTreeFlags |= LayerTreeFlagsIncludeRootLayerProperties;
2705     if (flags & Internals::LAYER_TREE_INCLUDES_EVENT_REGION)
2706         layerTreeFlags |= LayerTreeFlagsIncludeEventRegion;
2707     if (flags & Internals::LAYER_TREE_INCLUDES_DEEP_COLOR)
2708         layerTreeFlags |= LayerTreeFlagsIncludeDeepColor;
2709
2710     return layerTreeFlags;
2711 }
2712
2713 // FIXME: Remove the document argument. It is almost always the same as
2714 // contextDocument(), with the exception of a few tests that pass a
2715 // different document, and could just make the call through another Internals
2716 // instance instead.
2717 ExceptionOr<String> Internals::layerTreeAsText(Document& document, unsigned short flags) const
2718 {
2719     if (!document.frame())
2720         return Exception { InvalidAccessError };
2721
2722     document.updateLayoutIgnorePendingStylesheets();
2723     return document.frame()->layerTreeAsText(toLayerTreeFlags(flags));
2724 }
2725
2726 ExceptionOr<uint64_t> Internals::layerIDForElement(Element& element)
2727 {
2728     Document* document = contextDocument();
2729     if (!document || !document->frame())
2730         return Exception { InvalidAccessError };
2731
2732     element.document().updateLayoutIgnorePendingStylesheets();
2733
2734     if (!element.renderer() || !element.renderer()->hasLayer())
2735         return Exception { NotFoundError };
2736
2737     auto& layerModelObject = downcast<RenderLayerModelObject>(*element.renderer());
2738     if (!layerModelObject.layer()->isComposited())
2739         return Exception { NotFoundError };
2740
2741     auto* backing = layerModelObject.layer()->backing();
2742     return backing->graphicsLayer()->primaryLayerID();
2743 }
2744
2745 ExceptionOr<String> Internals::repaintRectsAsText() const
2746 {
2747     Document* document = contextDocument();
2748     if (!document || !document->frame())
2749         return Exception { InvalidAccessError };
2750
2751     return document->frame()->trackedRepaintRectsAsText();
2752 }
2753
2754 ExceptionOr<ScrollableArea*> Internals::scrollableAreaForNode(Node* node) const
2755 {
2756     if (!node)
2757         node = contextDocument();
2758
2759     if (!node)
2760         return Exception { InvalidAccessError };
2761
2762     auto nodeRef = makeRef(*node);
2763     nodeRef->document().updateLayoutIgnorePendingStylesheets();
2764
2765     ScrollableArea* scrollableArea = nullptr;
2766     if (is<Document>(nodeRef)) {
2767         auto* frameView = downcast<Document>(nodeRef.get()).view();
2768         if (!frameView)
2769             return Exception { InvalidAccessError };
2770
2771         scrollableArea = frameView;
2772     } else if (is<Element>(nodeRef)) {
2773         auto& element = downcast<Element>(nodeRef.get());
2774         if (!element.renderBox())
2775             return Exception { InvalidAccessError };
2776
2777         scrollableArea = element.renderBox()->layer();
2778     } else
2779         return Exception { InvalidNodeTypeError };
2780
2781     if (!scrollableArea)
2782         return Exception { InvalidNodeTypeError };
2783
2784     return scrollableArea;
2785 }
2786
2787 ExceptionOr<String> Internals::scrollbarOverlayStyle(Node* node) const
2788 {
2789     auto areaOrException = scrollableAreaForNode(node);
2790     if (areaOrException.hasException())
2791         return areaOrException.releaseException();
2792
2793     auto* scrollableArea = areaOrException.releaseReturnValue();
2794     switch (scrollableArea->scrollbarOverlayStyle()) {
2795     case ScrollbarOverlayStyleDefault:
2796         return "default"_str;
2797     case ScrollbarOverlayStyleDark:
2798         return "dark"_str;
2799     case ScrollbarOverlayStyleLight:
2800         return "light"_str;
2801     }
2802
2803     ASSERT_NOT_REACHED();
2804     return "unknown"_str;
2805 }
2806
2807 ExceptionOr<bool> Internals::scrollbarUsingDarkAppearance(Node* node) const
2808 {
2809     auto areaOrException = scrollableAreaForNode(node);
2810     if (areaOrException.hasException())
2811         return areaOrException.releaseException();
2812
2813     auto* scrollableArea = areaOrException.releaseReturnValue();
2814     return scrollableArea->useDarkAppearance();
2815 }
2816
2817 ExceptionOr<String> Internals::horizontalScrollbarState(Node* node) const
2818 {
2819     auto areaOrException = scrollableAreaForNode(node);
2820     if (areaOrException.hasException())
2821         return areaOrException.releaseException();
2822
2823     auto* scrollableArea = areaOrException.releaseReturnValue();
2824     return scrollableArea->horizontalScrollbarStateForTesting();
2825 }
2826
2827 ExceptionOr<String> Internals::verticalScrollbarState(Node* node) const
2828 {
2829     auto areaOrException = scrollableAreaForNode(node);
2830     if (areaOrException.hasException())
2831         return areaOrException.releaseException();
2832
2833     auto* scrollableArea = areaOrException.releaseReturnValue();
2834     return scrollableArea->verticalScrollbarStateForTesting();
2835 }
2836
2837 ExceptionOr<String> Internals::scrollingStateTreeAsText() const
2838 {
2839     Document* document = contextDocument();
2840     if (!document || !document->frame())
2841         return Exception { InvalidAccessError };
2842
2843     document->updateLayoutIgnorePendingStylesheets();
2844
2845     Page* page = document->page();
2846     if (!page)
2847         return String();
2848
2849     return page->scrollingStateTreeAsText();
2850 }
2851
2852 ExceptionOr<String> Internals::scrollingTreeAsText() const
2853 {
2854     Document* document = contextDocument();
2855     if (!document || !document->frame())
2856         return Exception { InvalidAccessError };
2857
2858     document->updateLayoutIgnorePendingStylesheets();
2859
2860     auto page = document->page();
2861     if (!page)
2862         return String();
2863
2864     auto scrollingCoordinator = page->scrollingCoordinator();
2865     if (!scrollingCoordinator)
2866         return String();
2867
2868     scrollingCoordinator->commitTreeStateIfNeeded();
2869     return scrollingCoordinator->scrollingTreeAsText();
2870 }
2871
2872 ExceptionOr<String> Internals::mainThreadScrollingReasons() const
2873 {
2874     Document* document = contextDocument();
2875     if (!document || !document->frame())
2876         return Exception { InvalidAccessError };
2877
2878     Page* page = document->page();
2879     if (!page)
2880         return String();
2881
2882     return page->synchronousScrollingReasonsAsText();
2883 }
2884
2885 ExceptionOr<Ref<DOMRectList>> Internals::nonFastScrollableRects() const
2886 {
2887     Document* document = contextDocument();
2888     if (!document || !document->frame())
2889         return Exception { InvalidAccessError };
2890
2891     Page* page = document->page();
2892     if (!page)
2893         return DOMRectList::create();
2894
2895     return page->nonFastScrollableRectsForTesting();
2896 }
2897
2898 ExceptionOr<void> Internals::setElementUsesDisplayListDrawing(Element& element, bool usesDisplayListDrawing)
2899 {
2900     Document* document = contextDocument();
2901     if (!document || !document->renderView())
2902         return Exception { InvalidAccessError };
2903
2904     element.document().updateLayoutIgnorePendingStylesheets();
2905
2906     if (!element.renderer())
2907         return Exception { InvalidAccessError };
2908
2909     if (is<HTMLCanvasElement>(element)) {
2910         downcast<HTMLCanvasElement>(element).setUsesDisplayListDrawing(usesDisplayListDrawing);
2911         return { };
2912     }
2913
2914     if (!element.renderer()->hasLayer())
2915         return Exception { InvalidAccessError };
2916
2917     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2918     if (!layer->isComposited())
2919         return Exception { InvalidAccessError };
2920
2921     layer->backing()->setUsesDisplayListDrawing(usesDisplayListDrawing);
2922     return { };
2923 }
2924
2925 ExceptionOr<void> Internals::setElementTracksDisplayListReplay(Element& element, bool isTrackingReplay)
2926 {
2927     Document* document = contextDocument();
2928     if (!document || !document->renderView())
2929         return Exception { InvalidAccessError };
2930
2931     element.document().updateLayoutIgnorePendingStylesheets();
2932
2933     if (!element.renderer())
2934         return Exception { InvalidAccessError };
2935
2936     if (is<HTMLCanvasElement>(element)) {
2937         downcast<HTMLCanvasElement>(element).setTracksDisplayListReplay(isTrackingReplay);
2938         return { };
2939     }
2940
2941     if (!element.renderer()->hasLayer())
2942         return Exception { InvalidAccessError };
2943
2944     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2945     if (!layer->isComposited())
2946         return Exception { InvalidAccessError };
2947
2948     layer->backing()->setIsTrackingDisplayListReplay(isTrackingReplay);
2949     return { };
2950 }
2951
2952 ExceptionOr<String> Internals::displayListForElement(Element& element, unsigned short flags)
2953 {
2954     Document* document = contextDocument();
2955     if (!document || !document->renderView())
2956         return Exception { InvalidAccessError };
2957
2958     element.document().updateLayoutIgnorePendingStylesheets();
2959
2960     if (!element.renderer())
2961         return Exception { InvalidAccessError };
2962
2963     DisplayList::AsTextFlags displayListFlags = 0;
2964     if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
2965         displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
2966
2967     if (is<HTMLCanvasElement>(element))
2968         return downcast<HTMLCanvasElement>(element).displayListAsText(displayListFlags);
2969
2970     if (!element.renderer()->hasLayer())
2971         return Exception { InvalidAccessError };
2972
2973     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
2974     if (!layer->isComposited())
2975         return Exception { InvalidAccessError };
2976
2977     return layer->backing()->displayListAsText(displayListFlags);
2978 }
2979
2980 ExceptionOr<String> Internals::replayDisplayListForElement(Element& element, unsigned short flags)
2981 {
2982     Document* document = contextDocument();
2983     if (!document || !document->renderView())
2984         return Exception { InvalidAccessError };
2985
2986     element.document().updateLayoutIgnorePendingStylesheets();
2987
2988     if (!element.renderer())
2989         return Exception { InvalidAccessError };
2990
2991     DisplayList::AsTextFlags displayListFlags = 0;
2992     if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
2993         displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
2994
2995     if (is<HTMLCanvasElement>(element))
2996         return downcast<HTMLCanvasElement>(element).replayDisplayListAsText(displayListFlags);
2997
2998     if (!element.renderer()->hasLayer())
2999         return Exception { InvalidAccessError };
3000
3001     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
3002     if (!layer->isComposited())
3003         return Exception { InvalidAccessError };
3004
3005     return layer->backing()->replayDisplayListAsText(displayListFlags);
3006 }
3007
3008 ExceptionOr<void> Internals::garbageCollectDocumentResources() const
3009 {
3010     Document* document = contextDocument();
3011     if (!document)
3012         return Exception { InvalidAccessError };
3013     document->cachedResourceLoader().garbageCollectDocumentResources();
3014     return { };
3015 }
3016
3017 bool Internals::isUnderMemoryPressure()
3018 {
3019     return MemoryPressureHandler::singleton().isUnderMemoryPressure();
3020 }
3021
3022 void Internals::beginSimulatedMemoryPressure()
3023 {
3024     MemoryPressureHandler::singleton().beginSimulatedMemoryPressure();
3025 }
3026
3027 void Internals::endSimulatedMemoryPressure()
3028 {
3029     MemoryPressureHandler::singleton().endSimulatedMemoryPressure();
3030 }
3031
3032 ExceptionOr<void> Internals::insertAuthorCSS(const String& css) const
3033 {
3034     Document* document = contextDocument();
3035     if (!document)
3036         return Exception { InvalidAccessError };
3037
3038     auto parsedSheet = StyleSheetContents::create(*document);
3039     parsedSheet.get().setIsUserStyleSheet(false);
3040     parsedSheet.get().parseString(css);
3041     document->extensionStyleSheets().addAuthorStyleSheetForTesting(WTFMove(parsedSheet));
3042     return { };
3043 }
3044
3045 ExceptionOr<void> Internals::insertUserCSS(const String& css) const
3046 {
3047     Document* document = contextDocument();
3048     if (!document)
3049         return Exception { InvalidAccessError };
3050
3051     auto parsedSheet = StyleSheetContents::create(*document);
3052     parsedSheet.get().setIsUserStyleSheet(true);
3053     parsedSheet.get().parseString(css);
3054     document->extensionStyleSheets().addUserStyleSheet(WTFMove(parsedSheet));
3055     return { };
3056 }
3057
3058 String Internals::counterValue(Element& element)
3059 {
3060     return counterValueForElement(&element);
3061 }
3062
3063 int Internals::pageNumber(Element& element, float pageWidth, float pageHeight)
3064 {
3065     return PrintContext::pageNumberForElement(&element, { pageWidth, pageHeight });
3066 }
3067
3068 Vector<String> Internals::shortcutIconURLs() const
3069 {
3070     if (!frame())
3071         return { };
3072     
3073     auto* documentLoader = frame()->loader().documentLoader();
3074     if (!documentLoader)
3075         return { };
3076
3077     Vector<String> result;
3078     for (auto& linkIcon : documentLoader->linkIcons())
3079         result.append(linkIcon.url.string());
3080     
3081     return result;
3082 }
3083
3084 int Internals::numberOfPages(float pageWidth, float pageHeight)
3085 {
3086     if (!frame())
3087         return -1;
3088
3089     return PrintContext::numberOfPages(*frame(), FloatSize(pageWidth, pageHeight));
3090 }
3091
3092 ExceptionOr<String> Internals::pageProperty(const String& propertyName, int pageNumber) const
3093 {
3094     if (!frame())
3095         return Exception { InvalidAccessError };
3096
3097     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
3098 }
3099
3100 ExceptionOr<String> Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
3101 {
3102     if (!frame())
3103         return Exception { InvalidAccessError };
3104
3105     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
3106 }
3107
3108 ExceptionOr<float> Internals::pageScaleFactor() const
3109 {
3110     Document* document = contextDocument();
3111     if (!document || !document->page())
3112         return Exception { InvalidAccessError };
3113
3114     return document->page()->pageScaleFactor();
3115 }
3116
3117 ExceptionOr<void> Internals::setPageScaleFactor(float scaleFactor, int x, int y)
3118 {
3119     Document* document = contextDocument();
3120     if (!document || !document->page())
3121         return Exception { InvalidAccessError };
3122
3123     document->page()->setPageScaleFactor(scaleFactor, IntPoint(x, y));
3124     return { };
3125 }
3126
3127 ExceptionOr<void> Internals::setPageZoomFactor(float zoomFactor)
3128 {
3129     Document* document = contextDocument();
3130     if (!document || !document->frame())
3131         return Exception { InvalidAccessError };
3132
3133     document->frame()->setPageZoomFactor(zoomFactor);
3134     return { };
3135 }
3136
3137 ExceptionOr<void> Internals::setTextZoomFactor(float zoomFactor)
3138 {
3139     Document* document = contextDocument();
3140     if (!document || !document->frame())
3141         return Exception { InvalidAccessError };
3142
3143     document->frame()->setTextZoomFactor(zoomFactor);
3144     return { };
3145 }
3146
3147 ExceptionOr<void> Internals::setUseFixedLayout(bool useFixedLayout)
3148 {
3149     Document* document = contextDocument();
3150     if (!document || !document->view())
3151         return Exception { InvalidAccessError };
3152
3153     document->view()->setUseFixedLayout(useFixedLayout);
3154     return { };
3155 }
3156
3157 ExceptionOr<void> Internals::setFixedLayoutSize(int width, int height)
3158 {
3159     Document* document = contextDocument();
3160     if (!document || !document->view())
3161         return Exception { InvalidAccessError };
3162
3163     document->view()->setFixedLayoutSize(IntSize(width, height));
3164     return { };
3165 }
3166
3167 ExceptionOr<void> Internals::setViewExposedRect(float x, float y, float width, float height)
3168 {
3169     Document* document = contextDocument();
3170     if (!document || !document->view())
3171         return Exception { InvalidAccessError };
3172
3173     document->view()->setViewExposedRect(FloatRect(x, y, width, height));
3174     return { };
3175 }
3176
3177 void Internals::setPrinting(int width, int height)
3178 {
3179     printContextForTesting() = makeUnique<PrintContext>(frame());
3180     printContextForTesting()->begin(width, height);
3181 }
3182
3183 void Internals::setHeaderHeight(float height)
3184 {
3185     Document* document = contextDocument();
3186     if (!document || !document->view())
3187         return;
3188
3189     document->page()->setHeaderHeight(height);
3190 }
3191
3192 void Internals::setFooterHeight(float height)
3193 {
3194     Document* document = contextDocument();
3195     if (!document || !document->view())
3196         return;
3197
3198     document->page()->setFooterHeight(height);
3199 }
3200
3201 void Internals::setTopContentInset(float contentInset)
3202 {
3203     Document* document = contextDocument();
3204     if (!document || !document->page())
3205         return;
3206
3207     document->page()->setTopContentInset(contentInset);
3208 }
3209
3210 #if ENABLE(FULLSCREEN_API)
3211
3212 void Internals::webkitWillEnterFullScreenForElement(Element& element)
3213 {
3214     Document* document = contextDocument();
3215     if (!document)
3216         return;
3217     document->fullscreenManager().willEnterFullscreen(element);
3218 }
3219
3220 void Internals::webkitDidEnterFullScreenForElement(Element&)
3221 {
3222     Document* document = contextDocument();
3223     if (!document)
3224         return;
3225     document->fullscreenManager().didEnterFullscreen();
3226 }
3227
3228 void Internals::webkitWillExitFullScreenForElement(Element&)
3229 {
3230     Document* document = contextDocument();
3231     if (!document)
3232         return;
3233     document->fullscreenManager().willExitFullscreen();
3234 }
3235
3236 void Internals::webkitDidExitFullScreenForElement(Element&)
3237 {
3238     Document* document = contextDocument();
3239     if (!document)
3240         return;
3241     document->fullscreenManager().didExitFullscreen();
3242 }
3243
3244 bool Internals::isAnimatingFullScreen() const
3245 {
3246     Document* document = contextDocument();
3247     if (!document)
3248         return false;
3249     return document->fullscreenManager().isAnimatingFullscreen();
3250 }
3251
3252 #endif
3253
3254 void Internals::setFullscreenInsets(FullscreenInsets insets)
3255 {
3256     Page* page = contextDocument()->frame()->page();
3257     ASSERT(page);
3258
3259     page->setFullscreenInsets(FloatBoxExtent(insets.top, insets.right, insets.bottom, insets.left));
3260 }
3261
3262 void Internals::setFullscreenAutoHideDuration(double duration)
3263 {
3264     Page* page = contextDocument()->frame()->page();
3265     ASSERT(page);
3266
3267     page->setFullscreenAutoHideDuration(Seconds(duration));
3268 }
3269
3270 void Internals::setFullscreenControlsHidden(bool hidden)
3271 {
3272     Page* page = contextDocument()->frame()->page();
3273     ASSERT(page);
3274
3275     page->setFullscreenControlsHidden(hidden);
3276 }
3277
3278 #if ENABLE(VIDEO_PRESENTATION_MODE)
3279 void Internals::setMockVideoPresentationModeEnabled(bool enabled)
3280 {
3281     Document* document = contextDocument();
3282     if (!document || !document->page())
3283         return;
3284
3285     document->page()->chrome().client().setMockVideoPresentationModeEnabled(enabled);
3286 }
3287 #endif
3288
3289 void Internals::setApplicationCacheOriginQuota(unsigned long long quota)
3290 {
3291     Document* document = contextDocument();
3292     if (!document || !document->page())
3293         return;
3294     document->page()->applicationCacheStorage().storeUpdatedQuotaForOrigin(&document->securityOrigin(), quota);
3295 }
3296
3297 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
3298 {
3299     LegacySchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
3300 }
3301
3302 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
3303 {
3304     LegacySchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
3305 }
3306
3307 void Internals::registerDefaultPortForProtocol(unsigned short port, const String& protocol)
3308 {
3309     registerDefaultPortForProtocolForTesting(port, protocol);
3310 }
3311
3312 Ref<MallocStatistics> Internals::mallocStatistics() const
3313 {
3314     return MallocStatistics::create();
3315 }
3316
3317 Ref<TypeConversions> Internals::typeConversions() const
3318 {
3319     return TypeConversions::create();
3320 }
3321
3322 Ref<MemoryInfo> Internals::memoryInfo() const
3323 {
3324     return MemoryInfo::create();
3325 }
3326
3327 Vector<String> Internals::getReferencedFilePaths() const
3328 {
3329     frame()->loader().history().saveDocumentAndScrollState();
3330     return FormController::referencedFilePaths(frame()->loader().history().currentItem()->documentState());
3331 }
3332
3333 ExceptionOr<void> Internals::startTrackingRepaints()
3334 {
3335     Document* document = contextDocument();
3336     if (!document || !document->view())
3337         return Exception { InvalidAccessError };
3338
3339     document->view()->setTracksRepaints(true);
3340     return { };
3341 }
3342
3343 ExceptionOr<void> Internals::stopTrackingRepaints()
3344 {
3345     Document* document = contextDocument();
3346     if (!document || !document->view())
3347         return Exception { InvalidAccessError };
3348
3349     document->view()->setTracksRepaints(false);
3350     return { };
3351 }
3352
3353 ExceptionOr<void> Internals::startTrackingLayerFlushes()
3354 {
3355     Document* document = contextDocument();
3356     if (!document || !document->renderView())
3357         return Exception { InvalidAccessError };
3358
3359     document->renderView()->compositor().startTrackingLayerFlushes();
3360     return { };
3361 }
3362
3363 ExceptionOr<unsigned> Internals::layerFlushCount()
3364 {
3365     Document* document = contextDocument();
3366     if (!document || !document->renderView())
3367         return Exception { InvalidAccessError };
3368
3369     return document->renderView()->compositor().layerFlushCount();
3370 }
3371
3372 ExceptionOr<void> Internals::startTrackingStyleRecalcs()
3373 {
3374     Document* document = contextDocument();
3375     if (!document)
3376         return Exception { InvalidAccessError };
3377
3378     document->startTrackingStyleRecalcs();
3379     return { };
3380 }
3381
3382 ExceptionOr<unsigned> Internals::styleRecalcCount()
3383 {
3384     Document* document = contextDocument();
3385     if (!document)
3386         return Exception { InvalidAccessError };
3387
3388     return document->styleRecalcCount();
3389 }
3390
3391 unsigned Internals::lastStyleUpdateSize() const
3392 {
3393     Document* document = contextDocument();
3394     if (!document)
3395         return 0;
3396     return document->lastStyleUpdateSizeForTesting();
3397 }
3398
3399 ExceptionOr<void> Internals::startTrackingCompositingUpdates()
3400 {
3401     Document* document = contextDocument();
3402     if (!document || !document->renderView())
3403         return Exception { InvalidAccessError };
3404
3405     document->renderView()->compositor().startTrackingCompositingUpdates();
3406     return { };
3407 }
3408
3409 ExceptionOr<unsigned> Internals::compositingUpdateCount()
3410 {
3411     Document* document = contextDocument();
3412     if (!document || !document->renderView())
3413         return Exception { InvalidAccessError };
3414
3415     return document->renderView()->compositor().compositingUpdateCount();
3416 }
3417
3418 ExceptionOr<void> Internals::setCompositingPolicyOverride(Optional<CompositingPolicy> policyOverride)
3419 {
3420     Document* document = contextDocument();
3421     if (!document)
3422         return Exception { InvalidAccessError };
3423
3424     if (!policyOverride) {
3425         document->page()->setCompositingPolicyOverride(WTF::nullopt);
3426         return { };
3427     }
3428
3429     switch (policyOverride.value()) {
3430     case Internals::CompositingPolicy::Normal:
3431         document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Normal);
3432         break;
3433     case Internals::CompositingPolicy::Conservative:
3434         document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Conservative);
3435         break;
3436     }
3437     
3438     return { };
3439 }
3440
3441 ExceptionOr<Optional<Internals::CompositingPolicy>> Internals::compositingPolicyOverride() const
3442 {
3443     Document* document = contextDocument();
3444     if (!document)
3445         return Exception { InvalidAccessError };
3446
3447     auto policyOverride = document->page()->compositingPolicyOverride();
3448     if (!policyOverride)
3449         return { WTF::nullopt };
3450
3451     switch (policyOverride.value()) {
3452     case WebCore::CompositingPolicy::Normal:
3453         return { Internals::CompositingPolicy::Normal };
3454     case WebCore::CompositingPolicy::Conservative:
3455         return { Internals::CompositingPolicy::Conservative };
3456     }
3457
3458     return { Internals::CompositingPolicy::Normal };
3459 }
3460
3461 void Internals::updateLayoutAndStyleForAllFrames()
3462 {
3463     auto* document = contextDocument();
3464     if (!document || !document->view())
3465         return;
3466     document->view()->updateLayoutAndStyleIfNeededRecursive();
3467 }
3468
3469 ExceptionOr<void> Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node)
3470 {
3471     Document* document;
3472     if (!node)
3473         document = contextDocument();
3474     else if (is<Document>(*node))
3475         document = downcast<Document>(node);
3476     else if (is<HTMLIFrameElement>(*node))
3477         document = downcast<HTMLIFrameElement>(*node).contentDocument();
3478     else
3479         return Exception { TypeError };
3480
3481     document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
3482     return { };
3483 }
3484
3485 unsigned Internals::layoutCount() const
3486 {
3487     Document* document = contextDocument();
3488     if (!document || !document->view())
3489         return 0;
3490     return document->view()->layoutContext().layoutCount();
3491 }
3492
3493 #if !PLATFORM(IOS_FAMILY)
3494 static const char* cursorTypeToString(Cursor::Type cursorType)
3495 {
3496     switch (cursorType) {
3497     case Cursor::Pointer: return "Pointer";
3498     case Cursor::Cross: return "Cross";
3499     case Cursor::Hand: return "Hand";
3500     case Cursor::IBeam: return "IBeam";
3501     case Cursor::Wait: return "Wait";
3502     case Cursor::Help: return "Help";
3503     case Cursor::EastResize: return "EastResize";
3504     case Cursor::NorthResize: return "NorthResize";
3505     case Cursor::NorthEastResize: return "NorthEastResize";
3506     case Cursor::NorthWestResize: return "NorthWestResize";
3507     case Cursor::SouthResize: return "SouthResize";
3508     case Cursor::SouthEastResize: return "SouthEastResize";
3509     case Cursor::SouthWestResize: return "SouthWestResize";
3510     case Cursor::WestResize: return "WestResize";
3511     case Cursor::NorthSouthResize: return "NorthSouthResize";
3512     case Cursor::EastWestResize: return "EastWestResize";
3513     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
3514     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
3515     case Cursor::ColumnResize: return "ColumnResize";
3516     case Cursor::RowResize: return "RowResize";
3517     case Cursor::MiddlePanning: return "MiddlePanning";
3518     case Cursor::EastPanning: return "EastPanning";
3519     case Cursor::NorthPanning: return "NorthPanning";
3520     case Cursor::NorthEastPanning: return "NorthEastPanning";
3521     case Cursor::NorthWestPanning: return "NorthWestPanning";
3522     case Cursor::SouthPanning: return "SouthPanning";
3523     case Cursor::SouthEastPanning: return "SouthEastPanning";
3524     case Cursor::SouthWestPanning: return "SouthWestPanning";
3525     case Cursor::WestPanning: return "WestPanning";
3526     case Cursor::Move: return "Move";
3527     case Cursor::VerticalText: return "VerticalText";
3528     case Cursor::Cell: return "Cell";
3529     case Cursor::ContextMenu: return "ContextMenu";
3530     case Cursor::Alias: return "Alias";
3531     case Cursor::Progress: return "Progress";
3532     case Cursor::NoDrop: return "NoDrop";
3533     case Cursor::Copy: return "Copy";
3534     case Cursor::None: return "None";
3535     case Cursor::NotAllowed: return "NotAllowed";
3536     case Cursor::ZoomIn: return "ZoomIn";
3537     case Cursor::ZoomOut: return "ZoomOut";
3538     case Cursor::Grab: return "Grab";
3539     case Cursor::Grabbing: return "Grabbing";
3540     case Cursor::Custom: return "Custom";
3541     }
3542
3543     ASSERT_NOT_REACHED();
3544     return "UNKNOWN";
3545 }
3546 #endif
3547
3548 ExceptionOr<String> Internals::getCurrentCursorInfo()
3549 {
3550     Document* document = contextDocument();
3551     if (!document || !document->frame())
3552         return Exception { InvalidAccessError };
3553
3554 #if !PLATFORM(IOS_FAMILY)
3555     Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
3556
3557     StringBuilder result;
3558     result.append("type=", cursorTypeToString(cursor.type()), " hotSpot=", cursor.hotSpot().x(), ',', cursor.hotSpot().y());
3559     if (cursor.image()) {
3560         FloatSize size = cursor.image()->size();
3561         result.append(" image=", size.width(), 'x', size.height());
3562     }
3563 #if ENABLE(MOUSE_CURSOR_SCALE)
3564     if (cursor.imageScaleFactor() != 1)
3565         result.append(" scale=", cursor.imageScaleFactor());
3566 #endif
3567     return result.toString();
3568 #else
3569     return "FAIL: Cursor details not available on this platform."_str;
3570 #endif
3571 }
3572
3573 Ref<ArrayBuffer> Internals::serializeObject(const RefPtr<SerializedScriptValue>& value) const
3574 {
3575     auto& bytes = value->data();
3576     return ArrayBuffer::create(bytes.data(), bytes.size());
3577 }
3578
3579 Ref<SerializedScriptValue> Internals::deserializeBuffer(ArrayBuffer& buffer) const
3580 {
3581     Vector<uint8_t> bytes;
3582     bytes.append(static_cast<const uint8_t*>(buffer.data()), buffer.byteLength());
3583     return SerializedScriptValue::adopt(WTFMove(bytes));
3584 }
3585
3586 bool Internals::isFromCurrentWorld(JSC::JSValue value) const
3587 {
3588     JSC::VM& vm = contextDocument()->vm();
3589     return isWorldCompatible(*vm.topCallFrame->lexicalGlobalObject(vm), value);
3590 }
3591
3592 JSC::JSValue Internals::evaluateInWorldIgnoringException(const String& name, const String& source)
3593 {
3594     auto* document = contextDocument();
3595     auto& scriptController = document->frame()->script();
3596     auto world = ScriptController::createWorld(name);
3597     return scriptController.executeScriptInWorldIgnoringException(world, source);
3598 }
3599
3600 void Internals::setUsesOverlayScrollbars(bool enabled)
3601 {
3602     WebCore::DeprecatedGlobalSettings::setUsesOverlayScrollbars(enabled);
3603 #if PLATFORM(MAC)
3604     ScrollerStyle::setUseOverlayScrollbars(enabled);
3605     ScrollbarTheme& theme = ScrollbarTheme::theme();
3606     if (theme.isMockTheme())
3607         return;
3608
3609     static_cast<ScrollbarThemeMac&>(theme).preferencesChanged();
3610 #endif
3611 }
3612
3613 void Internals::setUsesMockScrollAnimator(bool enabled)
3614 {
3615     WebCore::DeprecatedGlobalSettings::setUsesMockScrollAnimator(enabled);
3616 }
3617
3618 void Internals::forceReload(bool endToEnd)
3619 {
3620     OptionSet<ReloadOption> reloadOptions;
3621     if (endToEnd)
3622         reloadOptions.add(ReloadOption::FromOrigin);
3623
3624     frame()->loader().reload(reloadOptions);
3625 }
3626
3627 void Internals::reloadExpiredOnly()
3628 {
3629     frame()->loader().reload(ReloadOption::ExpiredOnly);
3630 }
3631
3632 void Internals::enableFixedWidthAutoSizeMode(bool enabled, int width, int height)
3633 {
3634     auto* document = contextDocument();
3635     if (!document || !document->view())
3636         return;
3637     document->view()->enableFixedWidthAutoSizeMode(enabled, { width, height });
3638 }
3639
3640 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
3641
3642 void Internals::initializeMockCDM()
3643 {
3644     LegacyCDM::registerCDMFactory([] (LegacyCDM* cdm) { return makeUnique<LegacyMockCDM>(cdm); },
3645         LegacyMockCDM::supportsKeySystem, LegacyMockCDM::supportsKeySystemAndMimeType);
3646 }
3647
3648 #endif
3649
3650 #if ENABLE(ENCRYPTED_MEDIA)
3651
3652 Ref<MockCDMFactory> Internals::registerMockCDM()
3653 {
3654     return MockCDMFactory::create();
3655 }
3656
3657 #endif
3658
3659 String Internals::markerTextForListItem(Element& element)
3660 {
3661     return WebCore::markerTextForListItem(&element);
3662 }
3663
3664 String Internals::toolTipFromElement(Element& element) const
3665 {
3666     HitTestResult result;
3667     result.setInnerNode(&element);
3668     TextDirection direction;
3669     return result.title(direction);
3670 }
3671
3672 String Internals::getImageSourceURL(Element& element)
3673 {
3674     return element.imageSourceURL();
3675 }
3676
3677 #if ENABLE(VIDEO)
3678
3679 Vector<String> Internals::mediaResponseSources(HTMLMediaElement& media)
3680 {
3681     auto* resourceLoader = media.lastMediaResourceLoaderForTesting();
3682     if (!resourceLoader)
3683         return { };
3684     Vector<String> result;
3685     auto responses = resourceLoader->responsesForTesting();
3686     for (auto& response : responses)
3687         result.append(responseSourceToString(response));
3688     return result;
3689 }
3690
3691 Vector<String> Internals::mediaResponseContentRanges(HTMLMediaElement& media)
3692 {
3693     auto* resourceLoader = media.lastMediaResourceLoaderForTesting();
3694     if (!resourceLoader)
3695         return { };
3696     Vector<String> result;
3697     auto responses = resourceLoader->responsesForTesting();
3698     for (auto& response : responses)
3699         result.append(response.httpHeaderField(HTTPHeaderName::ContentRange));
3700     return result;
3701 }
3702
3703 void Internals::simulateAudioInterruption(HTMLMediaElement& element)
3704 {
3705 #if USE(GSTREAMER)
3706     element.player()->simulateAudioInterruption();
3707 #else
3708     UNUSED_PARAM(element);
3709 #endif
3710 }
3711
3712 ExceptionOr<bool> Internals::mediaElementHasCharacteristic(HTMLMediaElement& element, const String& characteristic)
3713 {
3714     if (equalLettersIgnoringASCIICase(characteristic, "audible"))
3715         return element.hasAudio();
3716     if (equalLettersIgnoringASCIICase(characteristic, "visual"))
3717         return element.hasVideo();
3718     if (equalLettersIgnoringASCIICase(characteristic, "legible"))
3719         return element.hasClosedCaptions();
3720
3721     return Exception { SyntaxError };
3722 }
3723
3724 void Internals::beginSimulatedHDCPError(HTMLMediaElement& element)
3725 {
3726     if (auto player = element.player())
3727         player->beginSimulatedHDCPError();
3728 }
3729
3730 void Internals::endSimulatedHDCPError(HTMLMediaElement& element)
3731 {
3732     if (auto player = element.player())
3733         player->endSimulatedHDCPError();
3734 }
3735
3736 bool Internals::elementShouldBufferData(HTMLMediaElement& element)
3737 {
3738     return element.bufferingPolicy() < MediaPlayer::BufferingPolicy::LimitReadAhead;
3739 }
3740
3741 String Internals::elementBufferingPolicy(HTMLMediaElement& element)
3742 {
3743     switch (element.bufferingPolicy()) {
3744     case MediaPlayer::BufferingPolicy::Default:
3745         return "Default";
3746     case MediaPlayer::BufferingPolicy::LimitReadAhead:
3747         return "LimitReadAhead";
3748     case MediaPlayer::BufferingPolicy::MakeResourcesPurgeable:
3749         return "MakeResourcesPurgeable";
3750     case MediaPlayer::BufferingPolicy::PurgeResources:
3751         return "PurgeResources";
3752     }
3753
3754     ASSERT_NOT_REACHED();
3755     return "UNKNOWN";
3756 }
3757 #endif
3758
3759 bool Internals::isSelectPopupVisible(HTMLSelectElement& element)
3760 {
3761     element.document().updateLayoutIgnorePendingStylesheets();
3762
3763     auto* renderer = element.renderer();
3764     if (!is<RenderMenuList>(renderer))
3765         return false;
3766
3767 #if !PLATFORM(IOS_FAMILY)
3768     return downcast<RenderMenuList>(*renderer).popupIsVisible();
3769 #else
3770     return false;
3771 #endif
3772 }
3773
3774 ExceptionOr<String> Internals::captionsStyleSheetOverride()
3775 {
3776     Document* document = contextDocument();
3777     if (!document || !document->page())
3778         return Exception { InvalidAccessError };
3779
3780 #if ENABLE(VIDEO_TRACK)
3781     return document->page()->group().captionPreferences().captionsStyleSheetOverride();
3782 #else
3783     return String { emptyString() };
3784 #endif
3785 }
3786
3787 ExceptionOr<void> Internals::setCaptionsStyleSheetOverride(const String& override)
3788 {
3789     Document* document = contextDocument();
3790     if (!document || !document->page())
3791         return Exception { InvalidAccessError };
3792
3793 #if ENABLE(VIDEO_TRACK)
3794     document->page()->group().captionPreferences().setCaptionsStyleSheetOverride(override);
3795 #else
3796     UNUSED_PARAM(override);
3797 #endif
3798     return { };
3799 }
3800
3801 ExceptionOr<void> Internals::setPrimaryAudioTrackLanguageOverride(const String& language)
3802 {
3803     Document* document = contextDocument();
3804     if (!document || !document->page())
3805         return Exception { InvalidAccessError };
3806
3807 #if ENABLE(VIDEO_TRACK)
3808     document->page()->group().captionPreferences().setPrimaryAudioTrackLanguageOverride(language);
3809 #else
3810     UNUSED_PARAM(language);
3811 #endif
3812     return { };
3813 }
3814
3815 ExceptionOr<void> Internals::setCaptionDisplayMode(const String& mode)
3816 {
3817     Document* document = contextDocument();
3818     if (!document || !document->page())
3819         return Exception { InvalidAccessError };
3820
3821 #if ENABLE(VIDEO_TRACK)
3822     auto& captionPreferences = document->page()->group().captionPreferences();
3823
3824     if (equalLettersIgnoringASCIICase(mode, "automatic"))
3825         captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::Automatic);
3826     else if (equalLettersIgnoringASCIICase(mode, "forcedonly"))
3827         captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
3828     else if (equalLettersIgnoringASCIICase(mode, "alwayson"))
3829         captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn);
3830     else if (equalLettersIgnoringASCIICase(mode, "manual"))
3831         captionPreferences.setCaptionDisplayMode(CaptionUserPreferences::Manual);
3832     else
3833         return Exception { SyntaxError };
3834 #else
3835     UNUSED_PARAM(mode);
3836 #endif
3837     return { };
3838 }
3839
3840 #if ENABLE(VIDEO_TRACK)
3841 RefPtr<TextTrackCueGeneric> Internals::createGenericCue(double startTime, double endTime, String text)
3842 {
3843     Document* document = contextDocument();
3844     if (!document || !document->page())
3845         return nullptr;
3846     return TextTrackCueGeneric::create(*document, MediaTime::createWithDouble(startTime), MediaTime::createWithDouble(endTime), text);
3847 }
3848
3849 ExceptionOr<String> Internals::textTrackBCP47Language(TextTrack& track)
3850 {
3851     return String { track.validBCP47Language() };
3852 }
3853 #endif
3854
3855 #if ENABLE(VIDEO)
3856
3857 Ref<TimeRanges> Internals::createTimeRanges(Float32Array& startTimes, Float32Array& endTimes)
3858 {
3859     ASSERT(startTimes.length() == endTimes.length());
3860     Ref<TimeRanges> ranges = TimeRanges::create();
3861
3862     unsigned count = std::min(startTimes.length(), endTimes.length());
3863     for (unsigned i = 0; i < count; ++i)
3864         ranges->add(startTimes.item(i), endTimes.item(i));
3865     return ranges;
3866 }
3867
3868 double Internals::closestTimeToTimeRanges(double time, TimeRanges& ranges)
3869 {
3870     return ranges.nearest(time);
3871 }
3872
3873 #endif
3874
3875 ExceptionOr<Ref<DOMRect>> Internals::selectionBounds()
3876 {
3877     Document* document = contextDocument();
3878     if (!document || !document->frame())
3879         return Exception { InvalidAccessError };
3880
3881     return DOMRect::create(document->frame()->selection().selectionBounds());
3882 }
3883
3884 void Internals::setSelectionWithoutValidation(Ref<Node> baseNode, unsigned baseOffset, RefPtr<Node> extentNode, unsigned extentOffset)
3885 {
3886     contextDocument()->frame()->selection().moveTo(
3887         VisiblePosition { createLegacyEditingPosition(baseNode.ptr(), baseOffset) },
3888         VisiblePosition { createLegacyEditingPosition(extentNode.get(), extentOffset) });
3889 }
3890
3891 ExceptionOr<bool> Internals::isPluginUnavailabilityIndicatorObscured(Element& element)
3892 {
3893     if (!is<HTMLPlugInElement>(element))
3894         return Exception { InvalidAccessError };
3895
3896     return downcast<HTMLPlugInElement>(element).isReplacementObscured();
3897 }
3898
3899 ExceptionOr<String> Internals::unavailablePluginReplacementText(Element& element)
3900 {
3901     if (!is<HTMLPlugInElement>(element))
3902         return Exception { InvalidAccessError };
3903
3904     auto* renderer = element.renderer();
3905     if (!is<RenderEmbeddedObject>(renderer))
3906         return String { };
3907
3908     return String { downcast<RenderEmbeddedObject>(*renderer).pluginReplacementTextIfUnavailable() };
3909 }
3910
3911 bool Internals::isPluginSnapshotted(Element& element)
3912 {
3913     return is<HTMLPlugInElement>(element) && downcast<HTMLPlugInElement>(element).displayState() <= HTMLPlugInElement::DisplayingSnapshot;
3914 }
3915
3916 bool Internals::pluginIsBelowSizeThreshold(Element& element)
3917 {
3918     return is<HTMLPlugInElement>(element) && downcast<HTMLPlugInElement>(element).isBelowSizeThreshold();
3919 }
3920
3921 #if ENABLE(MEDIA_SOURCE)
3922
3923 void Internals::initializeMockMediaSource()
3924 {
3925 #if USE(AVFOUNDATION)
3926     WebCore::DeprecatedGlobalSettings::setAVFoundationEnabled(false);
3927 #endif
3928 #if USE(GSTREAMER)
3929     WebCore::DeprecatedGlobalSettings::setGStreamerEnabled(false);
3930 #endif
3931     MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
3932 }
3933
3934 Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer& buffer, const AtomString& trackID)
3935 {
3936     return buffer.bufferedSamplesForTrackID(trackID);
3937 }
3938
3939 Vector<String> Internals::enqueuedSamplesForTrackID(SourceBuffer& buffer, const AtomString& trackID)
3940 {
3941     return buffer.enqueuedSamplesForTrackID(trackID);
3942 }
3943
3944 double Internals::minimumUpcomingPresentationTimeForTrackID(SourceBuffer& buffer, const AtomString& trackID)
3945 {
3946     return buffer.minimumUpcomingPresentationTimeForTrackID(trackID).toDouble();
3947 }
3948
3949 void Internals::setShouldGenerateTimestamps(SourceBuffer& buffer, bool flag)
3950 {
3951     buffer.setShouldGenerateTimestamps(flag);
3952 }
3953
3954 void Internals::setMaximumQueueDepthForTrackID(SourceBuffer& buffer, const AtomString& trackID, size_t maxQueueDepth)
3955 {
3956     buffer.setMaximumQueueDepthForTrackID(trackID, maxQueueDepth);
3957 }
3958
3959 #endif
3960
3961 void Internals::enableMockMediaCapabilities()
3962 {
3963     MediaEngineConfigurationFactory::enableMock();
3964 }
3965
3966 #if ENABLE(VIDEO)
3967
3968 ExceptionOr<void> Internals::beginMediaSessionInterruption(const String& interruptionString)
3969 {
3970     PlatformMediaSession::InterruptionType interruption = PlatformMediaSession::SystemInterruption;
3971
3972     if (equalLettersIgnoringASCIICase(interruptionString, "system"))
3973         interruption = PlatformMediaSession::SystemInterruption;
3974     else if (equalLettersIgnoringASCIICase(interruptionString, "systemsleep"))
3975         interruption = PlatformMediaSession::SystemSleep;
3976     else if (equalLettersIgnoringASCIICase(interruptionString, "enteringbackground"))
3977         interruption = PlatformMediaSession::EnteringBackground;
3978     else if (equalLettersIgnoringASCIICase(interruptionString, "suspendedunderlock"))
3979         interruption = PlatformMediaSession::SuspendedUnderLock;
3980     else
3981         return Exception { InvalidAccessError };
3982
3983     PlatformMediaSessionManager::sharedManager().beginInterruption(interruption);
3984     return { };
3985 }
3986
3987 void Internals::endMediaSessionInterruption(const String& flagsString)
3988 {
3989     PlatformMediaSession::EndInterruptionFlags flags = PlatformMediaSession::NoFlags;
3990
3991     if (equalLettersIgnoringASCIICase(flagsString, "mayresumeplaying"))
3992         flags = PlatformMediaSession::MayResumePlaying;
3993
3994     PlatformMediaSessionManager::sharedManager().endInterruption(flags);
3995 }
3996
3997 void Internals::applicationWillBecomeInactive()
3998 {
3999     PlatformMediaSessionManager::sharedManager().applicationWillBecomeInactive();
4000 }
4001
4002 void Internals::applicationDidBecomeActive()
4003 {
4004     PlatformMediaSessionManager::sharedManager().applicationDidBecomeActive();
4005 }
4006
4007 void Internals::applicationWillEnterForeground(bool suspendedUnderLock) const
4008 {
4009     PlatformMediaSessionManager::sharedManager().applicationWillEnterForeground(suspendedUnderLock);
4010 }
4011
4012 void Internals::applicationDidEnterBackground(bool suspendedUnderLock) const
4013 {
4014     PlatformMediaSessionManager::sharedManager().applicationDidEnterBackground(suspendedUnderLock);
4015 }
4016
4017 static PlatformMediaSession::MediaType mediaTypeFromString(const String& mediaTypeString)
4018 {
4019     if (equalLettersIgnoringASCIICase(mediaTypeString, "video"))
4020         return PlatformMediaSession::MediaType::Video;
4021     if (equalLettersIgnoringASCIICase(mediaTypeString, "audio"))
4022         return PlatformMediaSession::MediaType::Audio;
4023     if (equalLettersIgnoringASCIICase(mediaTypeString, "videoaudio"))
4024         return PlatformMediaSession::MediaType::VideoAudio;
4025     if (equalLettersIgnoringASCIICase(mediaTypeString, "webaudio"))
4026         return PlatformMediaSession::MediaType::WebAudio;
4027
4028     return PlatformMediaSession::MediaType::None;
4029 }
4030
4031 ExceptionOr<void> Internals::setMediaSessionRestrictions(const String& mediaTypeString, StringView restrictionsString)
4032 {
4033     auto mediaType = mediaTypeFromString(mediaTypeString);
4034     if (mediaType == PlatformMediaSession::MediaType::None)
4035         return Exception { InvalidAccessError };
4036
4037     auto restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
4038     PlatformMediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions);
4039
4040     restrictions = PlatformMediaSessionManager::NoRestrictions;
4041
4042     for (StringView restrictionString : restrictionsString.split(',')) {
4043         if (equalLettersIgnoringASCIICase(restrictionString, "concurrentplaybacknotpermitted"))
4044             restrictions |= PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted;
4045         if (equalLettersIgnoringASCIICase(restrictionString, "backgroundprocessplaybackrestricted"))
4046             restrictions |= PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted;
4047         if (equalLettersIgnoringASCIICase(restrictionString, "backgroundtabplaybackrestricted"))
4048             restrictions |= PlatformMediaSessionManager::BackgroundTabPlaybackRestricted;
4049         if (equalLettersIgnoringASCIICase(restrictionString, "interruptedplaybacknotpermitted"))
4050             restrictions |= PlatformMediaSessionManager::InterruptedPlaybackNotPermitted;
4051         if (equalLettersIgnoringASCIICase(restrictionString, "inactiveprocessplaybackrestricted"))
4052             restrictions |= PlatformMediaSessionManager::InactiveProcessPlaybackRestricted;
4053         if (equalLettersIgnoringASCIICase(restrictionString, "suspendedunderlockplaybackrestricted"))
4054             restrictions |= PlatformMediaSessionManager::SuspendedUnderLockPlaybackRestricted;
4055     }
4056     PlatformMediaSessionManager::sharedManager().addRestriction(mediaType, restrictions);
4057     return { };
4058 }
4059
4060 ExceptionOr<String> Internals::mediaSessionRestrictions(const String& mediaTypeString) const
4061 {
4062     PlatformMediaSession::MediaType mediaType = mediaTypeFromString(mediaTypeString);
4063     if (mediaType == PlatformMediaSession::MediaType::None)
4064         return Exception { InvalidAccessError };
4065
4066     PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
4067     if (restrictions == PlatformMediaSessionManager::NoRestrictions)
4068         return String();
4069
4070     StringBuilder builder;
4071     if (restrictions & PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted)
4072         builder.append("concurrentplaybacknotpermitted");
4073     if (restrictions & PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted) {
4074         if (!builder.isEmpty())
4075             builder.append(',');
4076         builder.append("backgroundprocessplaybackrestricted");
4077     }
4078     if (restrictions & PlatformMediaSessionManager::BackgroundTabPlaybackRestricted) {
4079         if (!builder.isEmpty())
4080             builder.append(',');
4081         builder.append("backgroundtabplaybackrestricted");
4082     }
4083     if (restrictions & PlatformMediaSessionManager::InterruptedPlaybackNotPermitted) {
4084         if (!builder.isEmpty())
4085             builder.append(',');
4086         builder.append("interruptedplaybacknotpermitted");
4087     }
4088     return builder.toString();
4089 }
4090
4091 void Internals::setMediaElementRestrictions(HTMLMediaElement& element, StringView restrictionsString)
4092 {
4093     MediaElementSession::BehaviorRestrictions restrictions = element.mediaSession().behaviorRestrictions();
4094     element.mediaSession().removeBehaviorRestriction(restrictions);
4095
4096     restrictions = MediaElementSession::NoRestrictions;
4097
4098     for (StringView restrictionString : restrictionsString.split(',')) {
4099         if (equalLettersIgnoringASCIICase(restrictionString, "norestrictions"))
4100             restrictions |= MediaElementSession::NoRestrictions;
4101         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforload"))
4102             restrictions |= MediaElementSession::RequireUserGestureForLoad;
4103         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforvideoratechange"))
4104             restrictions |= MediaElementSession::RequireUserGestureForVideoRateChange;
4105         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforfullscreen"))
4106             restrictions |= MediaElementSession::RequireUserGestureForFullscreen;
4107         if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsenttoloadmedia"))
4108             restrictions |= MediaElementSession::RequirePageConsentToLoadMedia;
4109         if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsenttoresumemedia"))
4110             restrictions |= MediaElementSession::RequirePageConsentToResumeMedia;
4111 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
4112         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergesturetoshowplaybacktargetpicker"))
4113             restrictions |= MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker;
4114         if (equalLettersIgnoringASCIICase(restrictionString, "wirelessvideoplaybackdisabled"))
4115             restrictions |= MediaElementSession::WirelessVideoPlaybackDisabled;
4116 #endif
4117         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforaudioratechange"))
4118             restrictions |= MediaElementSession::RequireUserGestureForAudioRateChange;
4119         if (equalLettersIgnoringASCIICase(restrictionString, "autopreloadingnotpermitted"))
4120             restrictions |= MediaElementSession::AutoPreloadingNotPermitted;
4121         if (equalLettersIgnoringASCIICase(restrictionString, "invisibleautoplaynotpermitted"))
4122             restrictions |= MediaElementSession::InvisibleAutoplayNotPermitted;
4123         if (equalLettersIgnoringASCIICase(restrictionString, "overrideusergesturerequirementformaincontent"))
4124             restrictions |= MediaElementSession::OverrideUserGestureRequirementForMainContent;
4125         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergesturetocontrolcontrolsmanager"))
4126             restrictions |= MediaElementSession::RequireUserGestureToControlControlsManager;
4127         if (equalLettersIgnoringASCIICase(restrictionString, "requireplaybackTocontrolcontrolsmanager"))
4128             restrictions |= MediaElementSession::RequirePlaybackToControlControlsManager;
4129         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforvideoduetolowpowermode"))
4130             restrictions |= MediaElementSession::RequireUserGestureForVideoDueToLowPowerMode;
4131     }
4132     element.mediaSession().addBehaviorRestriction(restrictions);
4133 }
4134
4135 ExceptionOr<void> Internals::postRemoteControlCommand(const String& commandString, float argument)
4136 {
4137     PlatformMediaSession::RemoteControlCommandType command;
4138     PlatformMediaSession::RemoteCommandArgument parameter { argument };
4139
4140     if (equalLettersIgnoringASCIICase(commandString, "play"))
4141         command = PlatformMediaSession::PlayCommand;
4142     else if (equalLettersIgnoringASCIICase(commandString, "pause"))
4143         command = PlatformMediaSession::PauseCommand;
4144     else if (equalLettersIgnoringASCIICase(commandString, "stop"))
4145         command = PlatformMediaSession::StopCommand;
4146     else if (equalLettersIgnoringASCIICase(commandString, "toggleplaypause"))
4147         command = PlatformMediaSession::TogglePlayPauseCommand;
4148     else if (equalLettersIgnoringASCIICase(commandString, "beginseekingbackward"))
4149         command = PlatformMediaSession::BeginSeekingBackwardCommand;
4150     else if (equalLettersIgnoringASCIICase(commandString, "endseekingbackward"))
4151         command = PlatformMediaSession::EndSeekingBackwardCommand;
4152     else if (equalLettersIgnoringASCIICase(commandString, "beginseekingforward"))
4153         command = PlatformMediaSession::BeginSeekingForwardCommand;
4154     else if (equalLettersIgnoringASCIICase(commandString, "endseekingforward"))
4155         command = PlatformMediaSession::EndSeekingForwardCommand;
4156     else if (equalLettersIgnoringASCIICase(commandString, "seektoplaybackposition"))
4157         command = PlatformMediaSession::SeekToPlaybackPositionCommand;
4158     else
4159         return Exception { InvalidAccessError };
4160
4161     PlatformMediaSessionManager::sharedManager().processDidReceiveRemoteControlCommand(command, &parameter);
4162     return { };
4163 }
4164
4165 bool Internals::elementIsBlockingDisplaySleep(HTMLMediaElement& element) const
4166 {
4167     return element.isDisablingSleep();
4168 }
4169
4170 #endif // ENABLE(VIDEO)
4171
4172 #if ENABLE(MEDIA_SESSION)
4173
4174 void Internals::sendMediaSessionStartOfInterruptionNotification(MediaSessionInterruptingCategory category)
4175 {
4176     MediaSessionManager::singleton().didReceiveStartOfInterruptionNotification(category);
4177 }
4178
4179 void Internals::sendMediaSessionEndOfInterruptionNotification(MediaSessionInterruptingCategory category)
4180 {
4181     MediaSessionManager::singleton().didReceiveEndOfInterruptionNotification(category);
4182 }
4183
4184 String Internals::mediaSessionCurrentState(MediaSession* session) const
4185 {
4186     switch (session->currentState()) {
4187     case MediaSession::State::Active:
4188         return "active";
4189     case MediaSession::State::Interrupted:
4190         return "interrupted";
4191     case MediaSession::State::Idle:
4192         return "idle";
4193     }
4194 }
4195
4196 double Internals::mediaElementPlayerVolume(HTMLMediaElement* element) const
4197 {
4198     ASSERT_ARG(element, element);
4199     return element->playerVolume();
4200 }
4201
4202 void Internals::sendMediaControlEvent(MediaControlEvent event)
4203 {
4204     // FIXME: No good reason to use a single function with an argument instead of three functions.
4205     switch (event) {
4206     case MediControlEvent::PlayPause:
4207         MediaSessionManager::singleton().togglePlayback();
4208         break;
4209     case MediControlEvent::NextTrack:
4210         MediaSessionManager::singleton().skipToNextTrack();
4211         break;
4212     case MediControlEvent::PreviousTrack:
4213         MediaSessionManager::singleton().skipToPreviousTrack();
4214         break;
4215     }
4216 }
4217
4218 #endif // ENABLE(MEDIA_SESSION)
4219
4220 #if ENABLE(WEB_AUDIO)
4221 void Internals::setAudioContextRestrictions(AudioContext& context, StringView restrictionsString)
4222 {
4223     AudioContext::BehaviorRestrictions restrictions = context.behaviorRestrictions();
4224     context.removeBehaviorRestriction(restrictions);
4225
4226     restrictions = AudioContext::NoRestrictions;
4227
4228     for (StringView restrictionString : restrictionsString.split(',')) {
4229         if (equalLettersIgnoringASCIICase(restrictionString, "norestrictions"))
4230             restrictions |= AudioContext::NoRestrictions;
4231         if (equalLettersIgnoringASCIICase(restrictionString, "requireusergestureforaudiostart"))
4232             restrictions |= AudioContext::RequireUserGestureForAudioStartRestriction;
4233         if (equalLettersIgnoringASCIICase(restrictionString, "requirepageconsentforaudiostart"))
4234             restrictions |= AudioContext::RequirePageConsentForAudioStartRestriction;
4235     }
4236     context.addBehaviorRestriction(restrictions);
4237 }
4238
4239 void Internals::useMockAudioDestinationCocoa()
4240 {
4241 #if PLATFORM(COCOA)
4242     AudioDestinationCocoa::createOverride = MockAudioDestinationCocoa::create;
4243 #endif
4244 }
4245 #endif
4246
4247 void Internals::simulateSystemSleep() const
4248 {
4249 #if ENABLE(VIDEO)
4250     PlatformMediaSessionManager::sharedManager().processSystemWillSleep();
4251 #endif
4252 }
4253
4254 void Internals::simulateSystemWake() const
4255 {
4256 #if ENABLE(VIDEO)
4257     PlatformMediaSessionManager::sharedManager().processSystemDidWake();
4258 #endif
4259 }
4260
4261 ExceptionOr<Internals::NowPlayingState> Internals::nowPlayingState() const
4262 {
4263 #if ENABLE(VIDEO)
4264     return { { PlatformMediaSessionManager::sharedManager().lastUpdatedNowPlayingTitle(),
4265         PlatformMediaSessionManager::sharedManager().lastUpdatedNowPlayingDuration(),
4266         PlatformMediaSessionManager::sharedManager().lastUpdatedNowPlayingElapsedTime(),
4267         PlatformMediaSessionManager::sharedManager().lastUpdatedNowPlayingInfoUniqueIdentifier().toUInt64(),
4268         PlatformMediaSessionManager::sharedManager().hasActiveNowPlayingSession(),
4269         PlatformMediaSessionManager::sharedManager().registeredAsNowPlayingApplication()
4270     } };
4271 #else
4272     return Exception { InvalidAccessError };
4273 #endif
4274 }
4275
4276 #if ENABLE(VIDEO)
4277 RefPtr<HTMLMediaElement> Internals::bestMediaElementForShowingPlaybackControlsManager(Internals::PlaybackControlsPurpose purpose)
4278 {
4279     return HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager(purpose);
4280 }
4281
4282 Internals::MediaSessionState Internals::mediaSessionState(HTMLMediaElement& element)
4283 {
4284     return element.mediaSession().state();
4285 }
4286 #endif
4287
4288 ExceptionOr<Internals::MediaUsageState> Internals::mediaUsageState(HTMLMediaElement& element) const
4289 {
4290 #if ENABLE(VIDEO)
4291     element.mediaSession().updateMediaUsageIfChanged();
4292     auto info = element.mediaSession().mediaUsageInfo();
4293     if (!info)
4294         return Exception { NotSupportedError };
4295
4296     return { { info.value().mediaURL.string(),
4297         info.value().isPlaying,
4298         info.value().canShowControlsManager,
4299         info.value().canShowNowPlayingControls,
4300         info.value().isSuspended,
4301         info.value().isInActiveDocument,
4302         info.value().isFullscreen,
4303         info.value().isMuted,
4304         info.value().isMediaDocumentInMainFrame,
4305         info.value().isVideo,
4306         info.value().isAudio,
4307         info.value().hasVideo,
4308         info.value().hasAudio,
4309         info.value().hasRenderer,
4310         info.value().audioElementWithUserGesture,
4311         info.value().userHasPlayedAudioBefore,
4312         info.value().isElementRectMostlyInMainFrame,
4313         info.value().playbackPermitted,
4314         info.value().pageMediaPlaybackSuspended,
4315         info.value().isMediaDocumentAndNotOwnerElement,
4316         info.value().pageExplicitlyAllowsElementToAutoplayInline,
4317         info.value().requiresFullscreenForVideoPlaybackAndFullscreenNotPermitted,
4318         info.value().hasHadUserInteractionAndQuirksContainsShouldAutoplayForArbitraryUserGesture,
4319         info.value().isVideoAndRequiresUserGestureForVideoRateChange,
4320         info.value().isAudioAndRequiresUserGestureForAudioRateChange,
4321         info.value().isVideoAndRequiresUserGestureForVideoDueToLowPowerMode,
4322         info.value().noUserGestureRequired,
4323         info.value().requiresPlaybackAndIsNotPlaying,
4324         info.value().hasEverNotifiedAboutPlaying,
4325         info.value().outsideOfFullscreen,
4326         info.value().isLargeEnoughForMainContent,
4327     } };
4328
4329 #else
4330     UNUSED_PARAM(element);
4331     return Exception { InvalidAccessError };
4332 #endif
4333 }
4334
4335
4336 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
4337
4338 void Internals::setMockMediaPlaybackTargetPickerEnabled(bool enabled)
4339 {
4340     Page* page = contextDocument()->frame()->page();
4341     ASSERT(page);
4342
4343     page->setMockMediaPlaybackTargetPickerEnabled(enabled);
4344 }
4345
4346 ExceptionOr<void> Internals::setMockMediaPlaybackTargetPickerState(const String& deviceName, const String& deviceState)
4347 {
4348     Page* page = contextDocument()->frame()->page();
4349     ASSERT(page);
4350
4351     MediaPlaybackTargetContext::State state = MediaPlaybackTargetContext::Unknown;
4352
4353     if (equalLettersIgnoringASCIICase(deviceState, "deviceavailable"))
4354         state = MediaPlaybackTargetContext::OutputDeviceAvailable;
4355     else if (equalLettersIgnoringASCIICase(deviceState, "deviceunavailable"))
4356         state = MediaPlaybackTargetContext::OutputDeviceUnavailable;
4357     else if (equalLettersIgnoringASCIICase(deviceState, "unknown"))
4358         state = MediaPlaybackTargetContext::Unknown;
4359     else
4360         return Exception { InvalidAccessError };
4361
4362     page->setMockMediaPlaybackTargetPickerState(deviceName, state);
4363     return { };
4364 }
4365
4366 void Internals::mockMediaPlaybackTargetPickerDismissPopup()
4367 {
4368     auto* page = contextDocument()->frame()->page();
4369     ASSERT(page);
4370
4371     page->mockMediaPlaybackTargetPickerDismissPopup();
4372 }
4373
4374 #endif
4375
4376 ExceptionOr<Ref<MockPageOverlay>> Internals::installMockPageOverlay(PageOverlayType type)
4377 {
4378     Document* document = contextDocument();
4379     if (!document || !document->page())
4380         return Exception { InvalidAccessError };
4381
4382     return MockPageOverlayClient::singleton().installOverlay(*document->page(), type == PageOverlayType::View ? PageOverlay::OverlayType::View : PageOverlay::OverlayType::Document);
4383 }
4384
4385 ExceptionOr<String> Internals::pageOverlayLayerTreeAsText(unsigned short flags) const
4386 {
4387     Document* document = contextDocument();
4388     if (!document || !document->page())
4389         return Exception { InvalidAccessError };
4390
4391     document->updateLayoutIgnorePendingStylesheets();
4392
4393     return MockPageOverlayClient::singleton().layerTreeAsText(*document->page(), toLayerTreeFlags(flags));
4394 }
4395
4396 void Internals::setPageMuted(StringView statesString)
4397 {
4398     Document* document = contextDocument();
4399     if (!document)
4400         return;
4401
4402     WebCore::MediaProducer::MutedStateFlags state = MediaProducer::NoneMuted;
4403     for (StringView stateString : statesString.split(',')) {
4404         if (equalLettersIgnoringASCIICase(stateString, "audio"))
4405             state |= MediaProducer::AudioIsMuted;
4406         if (equalLettersIgnoringASCIICase(stateString, "capturedevices"))
4407             state |= MediaProducer::AudioAndVideoCaptureIsMuted;
4408         if (equalLettersIgnoringASCIICase(stateString, "screencapture"))
4409             state |= MediaProducer::ScreenCaptureIsMuted;
4410     }
4411
4412     if (Page* page = document->page())
4413         page->setMuted(state);
4414 }
4415
4416 String Internals::pageMediaState()
4417 {
4418     Document* document = contextDocument();
4419     if (!document || !document->page())
4420         return emptyString();
4421
4422     WebCore::MediaProducer::MediaStateFlags state = document->page()->mediaState();
4423     StringBuilder string;
4424     if (state & MediaProducer::IsPlayingAudio)
4425         string.append("IsPlayingAudio,");
4426     if (state & MediaProducer::IsPlayingVideo)
4427         string.append("IsPlayingVideo,");
4428     if (state & MediaProducer::IsPlayingToExternalDevice)
4429         string.append("IsPlayingToExternalDevice,");
4430     if (state & MediaProducer::RequiresPlaybackTargetMonitoring)
4431         string.append("RequiresPlaybackTargetMonitoring,");
4432     if (state & MediaProducer::ExternalDeviceAutoPlayCandidate)
4433         string.append("ExternalDeviceAutoPlayCandidate,");
4434     if (state & MediaProducer::DidPlayToEnd)
4435         string.append("DidPlayToEnd,");
4436     if (state & MediaProducer::IsSourceElementPlaying)
4437         string.append("IsSourceElementPlaying,");
4438
4439     if (state & MediaProducer::IsNextTrackControlEnabled)
4440         string.append("IsNextTrackControlEnabled,");
4441     if (state & MediaProducer::IsPreviousTrackControlEnabled)
4442         string.append("IsPreviousTrackControlEnabled,");
4443
4444     if (state & MediaProducer::HasPlaybackTargetAvailabilityListener)
4445         string.append("HasPlaybackTargetAvailabilityListener,");
4446     if (state & MediaProducer::HasAudioOrVideo)
4447         string.append("HasAudioOrVideo,");
4448     if (state & MediaProducer::HasActiveAudioCaptureDevice)
4449         string.append("HasActiveAudioCaptureDevice,");
4450     if (state & MediaProducer::HasActiveVideoCaptureDevice)
4451         string.append("HasActiveVideoCaptureDevice,");
4452     if (state & MediaProducer::HasMutedAudioCaptureDevice)
4453         string.append("HasMutedAudioCaptureDevice,");
4454     if (state & MediaProducer::HasMutedVideoCaptureDevice)
4455         string.append("HasMutedVideoCaptureDevice,");
4456     if (state & MediaProducer::HasUserInteractedWithMediaElement)
4457         string.append("HasUserInteractedWithMediaElement,");
4458     if (state & MediaProducer::HasActiveDisplayCaptureDevice)
4459         string.append("HasActiveDisplayCaptureDevice,");
4460     if (state & MediaProducer::HasMutedDisplayCaptureDevice)
4461         string.append("HasMutedDisplayCaptureDevice,");
4462
4463     if (string.isEmpty())
4464         string.append("IsNotPlaying");
4465     else
4466         string.resize(string.length() - 1);
4467
4468     return string.toString();
4469 }
4470
4471 void Internals::setPageDefersLoading(bool defersLoading)
4472 {
4473     Document* document = contextDocument();
4474     if (!document)
4475         return;
4476     if (Page* page = document->page())
4477         page->setDefersLoading(defersLoading);
4478 }
4479
4480 ExceptionOr<bool> Internals::pageDefersLoading()
4481 {
4482     Document* document = contextDocument();
4483     if (!document || !document->page())
4484         return Exception { InvalidAccessError };
4485     return document->page()->defersLoading();
4486 }
4487
4488 RefPtr<File> Internals::createFile(const String& path)
4489 {
4490     Document* document = contextDocument();
4491     if (!document)
4492         return nullptr;
4493
4494     URL url = document->completeURL(path);