REGRESSION (r260276): Scrolling through shelves on music.apple.com is not smooth
[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 (node == nodeRef->document().scrollingElement()) {
2845         auto* frameView = nodeRef->document().view();
2846         if (!frameView)
2847             return Exception { InvalidAccessError };
2848
2849         scrollableArea = frameView;
2850     } else if (is<Element>(nodeRef)) {
2851         auto& element = downcast<Element>(nodeRef.get());
2852         if (!element.renderBox())
2853             return Exception { InvalidAccessError };
2854
2855         auto& renderBox = *element.renderBox();
2856         if (!renderBox.canBeScrolledAndHasScrollableArea())
2857             return Exception { InvalidAccessError };
2858
2859         if (is<RenderListBox>(renderBox))
2860             scrollableArea = &downcast<RenderListBox>(renderBox);
2861         else
2862             scrollableArea = renderBox.layer();
2863     } else
2864         return Exception { InvalidNodeTypeError };
2865
2866     if (!scrollableArea)
2867         return Exception { InvalidNodeTypeError };
2868
2869     return scrollableArea;
2870 }
2871
2872 ExceptionOr<String> Internals::scrollbarOverlayStyle(Node* node) const
2873 {
2874     auto areaOrException = scrollableAreaForNode(node);
2875     if (areaOrException.hasException())
2876         return areaOrException.releaseException();
2877
2878     auto* scrollableArea = areaOrException.releaseReturnValue();
2879     switch (scrollableArea->scrollbarOverlayStyle()) {
2880     case ScrollbarOverlayStyleDefault:
2881         return "default"_str;
2882     case ScrollbarOverlayStyleDark:
2883         return "dark"_str;
2884     case ScrollbarOverlayStyleLight:
2885         return "light"_str;
2886     }
2887
2888     ASSERT_NOT_REACHED();
2889     return "unknown"_str;
2890 }
2891
2892 ExceptionOr<bool> Internals::scrollbarUsingDarkAppearance(Node* node) const
2893 {
2894     auto areaOrException = scrollableAreaForNode(node);
2895     if (areaOrException.hasException())
2896         return areaOrException.releaseException();
2897
2898     auto* scrollableArea = areaOrException.releaseReturnValue();
2899     return scrollableArea->useDarkAppearance();
2900 }
2901
2902 ExceptionOr<String> Internals::horizontalScrollbarState(Node* node) const
2903 {
2904     auto areaOrException = scrollableAreaForNode(node);
2905     if (areaOrException.hasException())
2906         return areaOrException.releaseException();
2907
2908     auto* scrollableArea = areaOrException.releaseReturnValue();
2909     return scrollableArea->horizontalScrollbarStateForTesting();
2910 }
2911
2912 ExceptionOr<String> Internals::verticalScrollbarState(Node* node) const
2913 {
2914     auto areaOrException = scrollableAreaForNode(node);
2915     if (areaOrException.hasException())
2916         return areaOrException.releaseException();
2917
2918     auto* scrollableArea = areaOrException.releaseReturnValue();
2919     return scrollableArea->verticalScrollbarStateForTesting();
2920 }
2921
2922 ExceptionOr<String> Internals::scrollingStateTreeAsText() const
2923 {
2924     Document* document = contextDocument();
2925     if (!document || !document->frame())
2926         return Exception { InvalidAccessError };
2927
2928     document->updateLayoutIgnorePendingStylesheets();
2929
2930     Page* page = document->page();
2931     if (!page)
2932         return String();
2933
2934     return page->scrollingStateTreeAsText();
2935 }
2936
2937 ExceptionOr<String> Internals::scrollingTreeAsText() const
2938 {
2939     Document* document = contextDocument();
2940     if (!document || !document->frame())
2941         return Exception { InvalidAccessError };
2942
2943     document->updateLayoutIgnorePendingStylesheets();
2944
2945     auto page = document->page();
2946     if (!page)
2947         return String();
2948
2949     auto scrollingCoordinator = page->scrollingCoordinator();
2950     if (!scrollingCoordinator)
2951         return String();
2952
2953     scrollingCoordinator->commitTreeStateIfNeeded();
2954     return scrollingCoordinator->scrollingTreeAsText();
2955 }
2956
2957 ExceptionOr<String> Internals::mainThreadScrollingReasons() const
2958 {
2959     Document* document = contextDocument();
2960     if (!document || !document->frame())
2961         return Exception { InvalidAccessError };
2962
2963     Page* page = document->page();
2964     if (!page)
2965         return String();
2966
2967     return page->synchronousScrollingReasonsAsText();
2968 }
2969
2970 ExceptionOr<Ref<DOMRectList>> Internals::nonFastScrollableRects() const
2971 {
2972     Document* document = contextDocument();
2973     if (!document || !document->frame())
2974         return Exception { InvalidAccessError };
2975
2976     Page* page = document->page();
2977     if (!page)
2978         return DOMRectList::create();
2979
2980     return page->nonFastScrollableRectsForTesting();
2981 }
2982
2983 ExceptionOr<void> Internals::setElementUsesDisplayListDrawing(Element& element, bool usesDisplayListDrawing)
2984 {
2985     Document* document = contextDocument();
2986     if (!document || !document->renderView())
2987         return Exception { InvalidAccessError };
2988
2989     element.document().updateLayoutIgnorePendingStylesheets();
2990
2991     if (!element.renderer())
2992         return Exception { InvalidAccessError };
2993
2994     if (is<HTMLCanvasElement>(element)) {
2995         downcast<HTMLCanvasElement>(element).setUsesDisplayListDrawing(usesDisplayListDrawing);
2996         return { };
2997     }
2998
2999     if (!element.renderer()->hasLayer())
3000         return Exception { InvalidAccessError };
3001
3002     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
3003     if (!layer->isComposited())
3004         return Exception { InvalidAccessError };
3005
3006     layer->backing()->setUsesDisplayListDrawing(usesDisplayListDrawing);
3007     return { };
3008 }
3009
3010 ExceptionOr<void> Internals::setElementTracksDisplayListReplay(Element& element, bool isTrackingReplay)
3011 {
3012     Document* document = contextDocument();
3013     if (!document || !document->renderView())
3014         return Exception { InvalidAccessError };
3015
3016     element.document().updateLayoutIgnorePendingStylesheets();
3017
3018     if (!element.renderer())
3019         return Exception { InvalidAccessError };
3020
3021     if (is<HTMLCanvasElement>(element)) {
3022         downcast<HTMLCanvasElement>(element).setTracksDisplayListReplay(isTrackingReplay);
3023         return { };
3024     }
3025
3026     if (!element.renderer()->hasLayer())
3027         return Exception { InvalidAccessError };
3028
3029     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
3030     if (!layer->isComposited())
3031         return Exception { InvalidAccessError };
3032
3033     layer->backing()->setIsTrackingDisplayListReplay(isTrackingReplay);
3034     return { };
3035 }
3036
3037 ExceptionOr<String> Internals::displayListForElement(Element& element, unsigned short flags)
3038 {
3039     Document* document = contextDocument();
3040     if (!document || !document->renderView())
3041         return Exception { InvalidAccessError };
3042
3043     element.document().updateLayoutIgnorePendingStylesheets();
3044
3045     if (!element.renderer())
3046         return Exception { InvalidAccessError };
3047
3048     DisplayList::AsTextFlags displayListFlags = 0;
3049     if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
3050         displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
3051
3052     if (is<HTMLCanvasElement>(element))
3053         return downcast<HTMLCanvasElement>(element).displayListAsText(displayListFlags);
3054
3055     if (!element.renderer()->hasLayer())
3056         return Exception { InvalidAccessError };
3057
3058     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
3059     if (!layer->isComposited())
3060         return Exception { InvalidAccessError };
3061
3062     return layer->backing()->displayListAsText(displayListFlags);
3063 }
3064
3065 ExceptionOr<String> Internals::replayDisplayListForElement(Element& element, unsigned short flags)
3066 {
3067     Document* document = contextDocument();
3068     if (!document || !document->renderView())
3069         return Exception { InvalidAccessError };
3070
3071     element.document().updateLayoutIgnorePendingStylesheets();
3072
3073     if (!element.renderer())
3074         return Exception { InvalidAccessError };
3075
3076     DisplayList::AsTextFlags displayListFlags = 0;
3077     if (flags & DISPLAY_LIST_INCLUDES_PLATFORM_OPERATIONS)
3078         displayListFlags |= DisplayList::AsTextFlag::IncludesPlatformOperations;
3079
3080     if (is<HTMLCanvasElement>(element))
3081         return downcast<HTMLCanvasElement>(element).replayDisplayListAsText(displayListFlags);
3082
3083     if (!element.renderer()->hasLayer())
3084         return Exception { InvalidAccessError };
3085
3086     RenderLayer* layer = downcast<RenderLayerModelObject>(element.renderer())->layer();
3087     if (!layer->isComposited())
3088         return Exception { InvalidAccessError };
3089
3090     return layer->backing()->replayDisplayListAsText(displayListFlags);
3091 }
3092
3093 ExceptionOr<void> Internals::garbageCollectDocumentResources() const
3094 {
3095     Document* document = contextDocument();
3096     if (!document)
3097         return Exception { InvalidAccessError };
3098     document->cachedResourceLoader().garbageCollectDocumentResources();
3099     return { };
3100 }
3101
3102 bool Internals::isUnderMemoryPressure()
3103 {
3104     return MemoryPressureHandler::singleton().isUnderMemoryPressure();
3105 }
3106
3107 void Internals::beginSimulatedMemoryPressure()
3108 {
3109     MemoryPressureHandler::singleton().beginSimulatedMemoryPressure();
3110 }
3111
3112 void Internals::endSimulatedMemoryPressure()
3113 {
3114     MemoryPressureHandler::singleton().endSimulatedMemoryPressure();
3115 }
3116
3117 ExceptionOr<void> Internals::insertAuthorCSS(const String& css) const
3118 {
3119     Document* document = contextDocument();
3120     if (!document)
3121         return Exception { InvalidAccessError };
3122
3123     auto parsedSheet = StyleSheetContents::create(*document);
3124     parsedSheet.get().setIsUserStyleSheet(false);
3125     parsedSheet.get().parseString(css);
3126     document->extensionStyleSheets().addAuthorStyleSheetForTesting(WTFMove(parsedSheet));
3127     return { };
3128 }
3129
3130 ExceptionOr<void> Internals::insertUserCSS(const String& css) const
3131 {
3132     Document* document = contextDocument();
3133     if (!document)
3134         return Exception { InvalidAccessError };
3135
3136     auto parsedSheet = StyleSheetContents::create(*document);
3137     parsedSheet.get().setIsUserStyleSheet(true);
3138     parsedSheet.get().parseString(css);
3139     document->extensionStyleSheets().addUserStyleSheet(WTFMove(parsedSheet));
3140     return { };
3141 }
3142
3143 String Internals::counterValue(Element& element)
3144 {
3145     return counterValueForElement(&element);
3146 }
3147
3148 int Internals::pageNumber(Element& element, float pageWidth, float pageHeight)
3149 {
3150     return PrintContext::pageNumberForElement(&element, { pageWidth, pageHeight });
3151 }
3152
3153 Vector<String> Internals::shortcutIconURLs() const
3154 {
3155     if (!frame())
3156         return { };
3157     
3158     auto* documentLoader = frame()->loader().documentLoader();
3159     if (!documentLoader)
3160         return { };
3161
3162     Vector<String> result;
3163     for (auto& linkIcon : documentLoader->linkIcons())
3164         result.append(linkIcon.url.string());
3165     
3166     return result;
3167 }
3168
3169 int Internals::numberOfPages(float pageWidth, float pageHeight)
3170 {
3171     if (!frame())
3172         return -1;
3173
3174     return PrintContext::numberOfPages(*frame(), FloatSize(pageWidth, pageHeight));
3175 }
3176
3177 ExceptionOr<String> Internals::pageProperty(const String& propertyName, int pageNumber) const
3178 {
3179     if (!frame())
3180         return Exception { InvalidAccessError };
3181
3182     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
3183 }
3184
3185 ExceptionOr<String> Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft) const
3186 {
3187     if (!frame())
3188         return Exception { InvalidAccessError };
3189
3190     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
3191 }
3192
3193 ExceptionOr<float> Internals::pageScaleFactor() const
3194 {
3195     Document* document = contextDocument();
3196     if (!document || !document->page())
3197         return Exception { InvalidAccessError };
3198
3199     return document->page()->pageScaleFactor();
3200 }
3201
3202 ExceptionOr<void> Internals::setPageScaleFactor(float scaleFactor, int x, int y)
3203 {
3204     Document* document = contextDocument();
3205     if (!document || !document->page())
3206         return Exception { InvalidAccessError };
3207
3208     document->page()->setPageScaleFactor(scaleFactor, IntPoint(x, y));
3209     return { };
3210 }
3211
3212 ExceptionOr<void> Internals::setPageZoomFactor(float zoomFactor)
3213 {
3214     Document* document = contextDocument();
3215     if (!document || !document->frame())
3216         return Exception { InvalidAccessError };
3217
3218     document->frame()->setPageZoomFactor(zoomFactor);
3219     return { };
3220 }
3221
3222 ExceptionOr<void> Internals::setTextZoomFactor(float zoomFactor)
3223 {
3224     Document* document = contextDocument();
3225     if (!document || !document->frame())
3226         return Exception { InvalidAccessError };
3227
3228     document->frame()->setTextZoomFactor(zoomFactor);
3229     return { };
3230 }
3231
3232 ExceptionOr<void> Internals::setUseFixedLayout(bool useFixedLayout)
3233 {
3234     Document* document = contextDocument();
3235     if (!document || !document->view())
3236         return Exception { InvalidAccessError };
3237
3238     document->view()->setUseFixedLayout(useFixedLayout);
3239     return { };
3240 }
3241
3242 ExceptionOr<void> Internals::setFixedLayoutSize(int width, int height)
3243 {
3244     Document* document = contextDocument();
3245     if (!document || !document->view())
3246         return Exception { InvalidAccessError };
3247
3248     document->view()->setFixedLayoutSize(IntSize(width, height));
3249     return { };
3250 }
3251
3252 ExceptionOr<void> Internals::setViewExposedRect(float x, float y, float width, float height)
3253 {
3254     Document* document = contextDocument();
3255     if (!document || !document->view())
3256         return Exception { InvalidAccessError };
3257
3258     document->view()->setViewExposedRect(FloatRect(x, y, width, height));
3259     return { };
3260 }
3261
3262 void Internals::setPrinting(int width, int height)
3263 {
3264     printContextForTesting() = makeUnique<PrintContext>(frame());
3265     printContextForTesting()->begin(width, height);
3266 }
3267
3268 void Internals::setHeaderHeight(float height)
3269 {
3270     Document* document = contextDocument();
3271     if (!document || !document->view())
3272         return;
3273
3274     document->page()->setHeaderHeight(height);
3275 }
3276
3277 void Internals::setFooterHeight(float height)
3278 {
3279     Document* document = contextDocument();
3280     if (!document || !document->view())
3281         return;
3282
3283     document->page()->setFooterHeight(height);
3284 }
3285
3286 void Internals::setTopContentInset(float contentInset)
3287 {
3288     Document* document = contextDocument();
3289     if (!document || !document->page())
3290         return;
3291
3292     document->page()->setTopContentInset(contentInset);
3293 }
3294
3295 #if ENABLE(FULLSCREEN_API)
3296
3297 void Internals::webkitWillEnterFullScreenForElement(Element& element)
3298 {
3299     Document* document = contextDocument();
3300     if (!document)
3301         return;
3302     document->fullscreenManager().willEnterFullscreen(element);
3303 }
3304
3305 void Internals::webkitDidEnterFullScreenForElement(Element&)
3306 {
3307     Document* document = contextDocument();
3308     if (!document)
3309         return;
3310     document->fullscreenManager().didEnterFullscreen();
3311 }
3312
3313 void Internals::webkitWillExitFullScreenForElement(Element&)
3314 {
3315     Document* document = contextDocument();
3316     if (!document)
3317         return;
3318     document->fullscreenManager().willExitFullscreen();
3319 }
3320
3321 void Internals::webkitDidExitFullScreenForElement(Element&)
3322 {
3323     Document* document = contextDocument();
3324     if (!document)
3325         return;
3326     document->fullscreenManager().didExitFullscreen();
3327 }
3328
3329 bool Internals::isAnimatingFullScreen() const
3330 {
3331     Document* document = contextDocument();
3332     if (!document)
3333         return false;
3334     return document->fullscreenManager().isAnimatingFullscreen();
3335 }
3336
3337 #endif
3338
3339 void Internals::setFullscreenInsets(FullscreenInsets insets)
3340 {
3341     Page* page = contextDocument()->frame()->page();
3342     ASSERT(page);
3343
3344     page->setFullscreenInsets(FloatBoxExtent(insets.top, insets.right, insets.bottom, insets.left));
3345 }
3346
3347 void Internals::setFullscreenAutoHideDuration(double duration)
3348 {
3349     Page* page = contextDocument()->frame()->page();
3350     ASSERT(page);
3351
3352     page->setFullscreenAutoHideDuration(Seconds(duration));
3353 }
3354
3355 void Internals::setFullscreenControlsHidden(bool hidden)
3356 {
3357     Page* page = contextDocument()->frame()->page();
3358     ASSERT(page);
3359
3360     page->setFullscreenControlsHidden(hidden);
3361 }
3362
3363 #if ENABLE(VIDEO_PRESENTATION_MODE)
3364 void Internals::setMockVideoPresentationModeEnabled(bool enabled)
3365 {
3366     Document* document = contextDocument();
3367     if (!document || !document->page())
3368         return;
3369
3370     document->page()->chrome().client().setMockVideoPresentationModeEnabled(enabled);
3371 }
3372 #endif
3373
3374 void Internals::setApplicationCacheOriginQuota(unsigned long long quota)
3375 {
3376     Document* document = contextDocument();
3377     if (!document || !document->page())
3378         return;
3379     document->page()->applicationCacheStorage().storeUpdatedQuotaForOrigin(&document->securityOrigin(), quota);
3380 }
3381
3382 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
3383 {
3384     LegacySchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
3385 }
3386
3387 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
3388 {
3389     LegacySchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
3390 }
3391
3392 void Internals::registerDefaultPortForProtocol(unsigned short port, const String& protocol)
3393 {
3394     registerDefaultPortForProtocolForTesting(port, protocol);
3395 }
3396
3397 Ref<MallocStatistics> Internals::mallocStatistics() const
3398 {
3399     return MallocStatistics::create();
3400 }
3401
3402 Ref<TypeConversions> Internals::typeConversions() const
3403 {
3404     return TypeConversions::create();
3405 }
3406
3407 Ref<MemoryInfo> Internals::memoryInfo() const
3408 {
3409     return MemoryInfo::create();
3410 }
3411
3412 Vector<String> Internals::getReferencedFilePaths() const
3413 {
3414     frame()->loader().history().saveDocumentAndScrollState();
3415     return FormController::referencedFilePaths(frame()->loader().history().currentItem()->documentState());
3416 }
3417
3418 ExceptionOr<void> Internals::startTrackingRepaints()
3419 {
3420     Document* document = contextDocument();
3421     if (!document || !document->view())
3422         return Exception { InvalidAccessError };
3423
3424     document->view()->setTracksRepaints(true);
3425     return { };
3426 }
3427
3428 ExceptionOr<void> Internals::stopTrackingRepaints()
3429 {
3430     Document* document = contextDocument();
3431     if (!document || !document->view())
3432         return Exception { InvalidAccessError };
3433
3434     document->view()->setTracksRepaints(false);
3435     return { };
3436 }
3437
3438 ExceptionOr<void> Internals::startTrackingLayerFlushes()
3439 {
3440     Document* document = contextDocument();
3441     if (!document || !document->renderView())
3442         return Exception { InvalidAccessError };
3443
3444     document->renderView()->compositor().startTrackingLayerFlushes();
3445     return { };
3446 }
3447
3448 ExceptionOr<unsigned> Internals::layerFlushCount()
3449 {
3450     Document* document = contextDocument();
3451     if (!document || !document->renderView())
3452         return Exception { InvalidAccessError };
3453
3454     return document->renderView()->compositor().layerFlushCount();
3455 }
3456
3457 ExceptionOr<void> Internals::startTrackingStyleRecalcs()
3458 {
3459     Document* document = contextDocument();
3460     if (!document)
3461         return Exception { InvalidAccessError };
3462
3463     document->startTrackingStyleRecalcs();
3464     return { };
3465 }
3466
3467 ExceptionOr<unsigned> Internals::styleRecalcCount()
3468 {
3469     Document* document = contextDocument();
3470     if (!document)
3471         return Exception { InvalidAccessError };
3472
3473     return document->styleRecalcCount();
3474 }
3475
3476 unsigned Internals::lastStyleUpdateSize() const
3477 {
3478     Document* document = contextDocument();
3479     if (!document)
3480         return 0;
3481     return document->lastStyleUpdateSizeForTesting();
3482 }
3483
3484 ExceptionOr<void> Internals::startTrackingCompositingUpdates()
3485 {
3486     Document* document = contextDocument();
3487     if (!document || !document->renderView())
3488         return Exception { InvalidAccessError };
3489
3490     document->renderView()->compositor().startTrackingCompositingUpdates();
3491     return { };
3492 }
3493
3494 ExceptionOr<unsigned> Internals::compositingUpdateCount()
3495 {
3496     Document* document = contextDocument();
3497     if (!document || !document->renderView())
3498         return Exception { InvalidAccessError };
3499
3500     return document->renderView()->compositor().compositingUpdateCount();
3501 }
3502
3503 ExceptionOr<void> Internals::setCompositingPolicyOverride(Optional<CompositingPolicy> policyOverride)
3504 {
3505     Document* document = contextDocument();
3506     if (!document)
3507         return Exception { InvalidAccessError };
3508
3509     if (!policyOverride) {
3510         document->page()->setCompositingPolicyOverride(WTF::nullopt);
3511         return { };
3512     }
3513
3514     switch (policyOverride.value()) {
3515     case Internals::CompositingPolicy::Normal:
3516         document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Normal);
3517         break;
3518     case Internals::CompositingPolicy::Conservative:
3519         document->page()->setCompositingPolicyOverride(WebCore::CompositingPolicy::Conservative);
3520         break;
3521     }
3522     
3523     return { };
3524 }
3525
3526 ExceptionOr<Optional<Internals::CompositingPolicy>> Internals::compositingPolicyOverride() const
3527 {
3528     Document* document = contextDocument();
3529     if (!document)
3530         return Exception { InvalidAccessError };
3531
3532     auto policyOverride = document->page()->compositingPolicyOverride();
3533     if (!policyOverride)
3534         return { WTF::nullopt };
3535
3536     switch (policyOverride.value()) {
3537     case WebCore::CompositingPolicy::Normal:
3538         return { Internals::CompositingPolicy::Normal };
3539     case WebCore::CompositingPolicy::Conservative:
3540         return { Internals::CompositingPolicy::Conservative };
3541     }
3542
3543     return { Internals::CompositingPolicy::Normal };
3544 }
3545
3546 void Internals::updateLayoutAndStyleForAllFrames()
3547 {
3548     auto* document = contextDocument();
3549     if (!document || !document->view())
3550         return;
3551     document->view()->updateLayoutAndStyleIfNeededRecursive();
3552 }
3553
3554 ExceptionOr<void> Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node)
3555 {
3556     Document* document;
3557     if (!node)
3558         document = contextDocument();
3559     else if (is<Document>(*node))
3560         document = downcast<Document>(node);
3561     else if (is<HTMLIFrameElement>(*node))
3562         document = downcast<HTMLIFrameElement>(*node).contentDocument();
3563     else
3564         return Exception { TypeError };
3565
3566     document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
3567     return { };
3568 }
3569
3570 unsigned Internals::layoutCount() const
3571 {
3572     Document* document = contextDocument();
3573     if (!document || !document->view())
3574         return 0;
3575     return document->view()->layoutContext().layoutCount();
3576 }
3577
3578 #if !PLATFORM(IOS_FAMILY)
3579 static const char* cursorTypeToString(Cursor::Type cursorType)
3580 {
3581     switch (cursorType) {
3582     case Cursor::Pointer: return "Pointer";
3583     case Cursor::Cross: return "Cross";
3584     case Cursor::Hand: return "Hand";
3585     case Cursor::IBeam: return "IBeam";
3586     case Cursor::Wait: return "Wait";
3587     case Cursor::Help: return "Help";
3588     case Cursor::EastResize: return "EastResize";
3589     case Cursor::NorthResize: return "NorthResize";
3590     case Cursor::NorthEastResize: return "NorthEastResize";
3591     case Cursor::NorthWestResize: return "NorthWestResize";
3592     case Cursor::SouthResize: return "SouthResize";
3593     case Cursor::SouthEastResize: return "SouthEastResize";
3594     case Cursor::SouthWestResize: return "SouthWestResize";
3595     case Cursor::WestResize: return "WestResize";
3596     case Cursor::NorthSouthResize: return "NorthSouthResize";
3597     case Cursor::EastWestResize: return "EastWestResize";
3598     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
3599     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
3600     case Cursor::ColumnResize: return "ColumnResize";
3601     case Cursor::RowResize: return "RowResize";
3602     case Cursor::MiddlePanning: return "MiddlePanning";
3603     case Cursor::EastPanning: return "EastPanning";
3604     case Cursor::NorthPanning: return "NorthPanning";
3605     case Cursor::NorthEastPanning: return "NorthEastPanning";
3606     case Cursor::NorthWestPanning: return "NorthWestPanning";
3607     case Cursor::SouthPanning: return "SouthPanning";
3608     case Cursor::SouthEastPanning: return "SouthEastPanning";
3609     case Cursor::SouthWestPanning: return "SouthWestPanning";
3610     case Cursor::WestPanning: return "WestPanning";
3611     case Cursor::Move: return "Move";
3612     case Cursor::VerticalText: return "VerticalText";
3613     case Cursor::Cell: return "Cell";
3614     case Cursor::ContextMenu: return "ContextMenu";
3615     case Cursor::Alias: return "Alias";
3616     case Cursor::Progress: return "Progress";
3617     case Cursor::NoDrop: return "NoDrop";
3618     case Cursor::Copy: return "Copy";
3619     case Cursor::None: return "None";
3620     case Cursor::NotAllowed: return "NotAllowed";
3621     case Cursor::ZoomIn: return "ZoomIn";
3622     case Cursor::ZoomOut: return "ZoomOut";
3623     case Cursor::Grab: return "Grab";
3624     case Cursor::Grabbing: return "Grabbing";
3625     case Cursor::Custom: return "Custom";
3626     }
3627
3628     ASSERT_NOT_REACHED();
3629     return "UNKNOWN";
3630 }
3631 #endif
3632
3633 ExceptionOr<String> Internals::getCurrentCursorInfo()
3634 {
3635     Document* document = contextDocument();
3636     if (!document || !document->frame())
3637         return Exception { InvalidAccessError };
3638
3639 #if !PLATFORM(IOS_FAMILY)
3640     Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
3641
3642     StringBuilder result;
3643     result.append("type=", cursorTypeToString(cursor.type()), " hotSpot=", cursor.hotSpot().x(), ',', cursor.hotSpot().y());
3644     if (cursor.image()) {
3645         FloatSize size = cursor.image()->size();
3646         result.append(" image=", size.width(), 'x', size.height());
3647     }
3648 #if ENABLE(MOUSE_CURSOR_SCALE)
3649     if (cursor.imageScaleFactor() != 1)
3650         result.append(" scale=", cursor.imageScaleFactor());
3651 #endif
3652     return result.toString();
3653 #else
3654     return "FAIL: Cursor details not available on this platform."_str;
3655 #endif
3656 }
3657
3658 Ref<ArrayBuffer> Internals::serializeObject(const RefPtr<SerializedScriptValue>& value) const
3659 {
3660     auto& bytes = value->data();
3661     return ArrayBuffer::create(bytes.data(), bytes.size());
3662 }
3663
3664 Ref<SerializedScriptValue> Internals::deserializeBuffer(ArrayBuffer& buffer) const
3665 {
3666     Vector<uint8_t> bytes;
3667     bytes.append(static_cast<const uint8_t*>(buffer.data()), buffer.byteLength());
3668     return SerializedScriptValue::adopt(WTFMove(bytes));
3669 }
3670
3671 bool Internals::isFromCurrentWorld(JSC::JSValue value) const
3672 {
3673     JSC::VM& vm = contextDocument()->vm();
3674     return isWorldCompatible(*vm.topCallFrame->lexicalGlobalObject(vm), value);
3675 }
3676
3677 JSC::JSValue Internals::evaluateInWorldIgnoringException(const String& name, const String& source)
3678 {
3679     auto* document = contextDocument();
3680     auto& scriptController = document->frame()->script();
3681     auto world = ScriptController::createWorld(name);
3682     return scriptController.executeScriptInWorldIgnoringException(world, source);
3683 }
3684
3685 void Internals::setUsesOverlayScrollbars(bool enabled)
3686 {
3687     WebCore::DeprecatedGlobalSettings::setUsesOverlayScrollbars(enabled);
3688 #if PLATFORM(MAC)
3689     ScrollerStyle::setUseOverlayScrollbars(enabled);
3690     ScrollbarTheme& theme = ScrollbarTheme::theme();
3691     if (theme.isMockTheme())
3692         return;
3693
3694     static_cast<ScrollbarThemeMac&>(theme).preferencesChanged();
3695 #endif
3696 }
3697
3698 void Internals::setUsesMockScrollAnimator(bool enabled)
3699 {
3700     WebCore::DeprecatedGlobalSettings::setUsesMockScrollAnimator(enabled);
3701 }
3702
3703 void Internals::forceReload(bool endToEnd)
3704 {
3705     OptionSet<ReloadOption> reloadOptions;
3706     if (endToEnd)
3707         reloadOptions.add(ReloadOption::FromOrigin);
3708
3709     frame()->loader().reload(reloadOptions);
3710 }
3711
3712 void Internals::reloadExpiredOnly()
3713 {
3714     frame()->l