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