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