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