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