Make shrink-wrapping test a ref-test instead of pixel-test
[WebKit-https.git] / Source / WebCore / testing / Internals.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  * Copyright (C) 2013, 2014 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 "AnimationController.h"
32 #include "ApplicationCacheStorage.h"
33 #include "BackForwardController.h"
34 #include "CachedImage.h"
35 #include "CachedResourceLoader.h"
36 #include "Chrome.h"
37 #include "ChromeClient.h"
38 #include "ClientRect.h"
39 #include "ClientRectList.h"
40 #include "ContentDistributor.h"
41 #include "Cursor.h"
42 #include "DOMPath.h"
43 #include "DOMStringList.h"
44 #include "DOMWindow.h"
45 #include "Document.h"
46 #include "DocumentMarker.h"
47 #include "DocumentMarkerController.h"
48 #include "Editor.h"
49 #include "Element.h"
50 #include "EventHandler.h"
51 #include "ExceptionCode.h"
52 #include "File.h"
53 #include "FontCache.h"
54 #include "FormController.h"
55 #include "FrameLoader.h"
56 #include "FrameView.h"
57 #include "HTMLIFrameElement.h"
58 #include "HTMLImageElement.h"
59 #include "HTMLInputElement.h"
60 #include "HTMLLinkElement.h"
61 #include "HTMLNames.h"
62 #include "HTMLPlugInElement.h"
63 #include "HTMLPreloadScanner.h"
64 #include "HTMLSelectElement.h"
65 #include "HTMLTextAreaElement.h"
66 #include "HTMLVideoElement.h"
67 #include "HistoryController.h"
68 #include "HistoryItem.h"
69 #include "IconController.h"
70 #include "InspectorClient.h"
71 #include "InspectorController.h"
72 #include "InspectorForwarding.h"
73 #include "InspectorFrontendClientLocal.h"
74 #include "InspectorInstrumentation.h"
75 #include "InspectorOverlay.h"
76 #include "InstrumentingAgents.h"
77 #include "IntRect.h"
78 #include "InternalSettings.h"
79 #include "Language.h"
80 #include "MainFrame.h"
81 #include "MallocStatistics.h"
82 #include "MediaPlayer.h"
83 #include "MemoryCache.h"
84 #include "MemoryInfo.h"
85 #include "MicroTask.h"
86 #include "MicroTaskTest.h"
87 #include "MockPageOverlayClient.h"
88 #include "Page.h"
89 #include "PageCache.h"
90 #include "PageOverlay.h"
91 #include "PathUtilities.h"
92 #include "PlatformMediaSessionManager.h"
93 #include "PrintContext.h"
94 #include "PseudoElement.h"
95 #include "Range.h"
96 #include "RenderEmbeddedObject.h"
97 #include "RenderLayerCompositor.h"
98 #include "RenderMenuList.h"
99 #include "RenderTreeAsText.h"
100 #include "RenderView.h"
101 #include "RenderedDocumentMarker.h"
102 #include "RuntimeEnabledFeatures.h"
103 #include "SchemeRegistry.h"
104 #include "ScriptedAnimationController.h"
105 #include "ScrollingCoordinator.h"
106 #include "SerializedScriptValue.h"
107 #include "Settings.h"
108 #include "ShadowRoot.h"
109 #include "SourceBuffer.h"
110 #include "SpellChecker.h"
111 #include "StaticNodeList.h"
112 #include "StyleSheetContents.h"
113 #include "TextIterator.h"
114 #include "TreeScope.h"
115 #include "TypeConversions.h"
116 #include "ViewportArguments.h"
117 #include "WebConsoleAgent.h"
118 #include "WorkerThread.h"
119 #include "XMLHttpRequest.h"
120 #include <JavaScriptCore/Profile.h>
121 #include <bytecode/CodeBlock.h>
122 #include <inspector/InspectorAgentBase.h>
123 #include <inspector/InspectorValues.h>
124 #include <runtime/JSCInlines.h>
125 #include <runtime/JSCJSValue.h>
126 #include <wtf/text/CString.h>
127 #include <wtf/text/StringBuffer.h>
128
129 #if ENABLE(INPUT_TYPE_COLOR)
130 #include "ColorChooser.h"
131 #endif
132
133 #if ENABLE(BATTERY_STATUS)
134 #include "BatteryController.h"
135 #endif
136
137 #if ENABLE(PROXIMITY_EVENTS)
138 #include "DeviceProximityController.h"
139 #endif
140
141 #if ENABLE(MOUSE_CURSOR_SCALE)
142 #include <wtf/dtoa.h>
143 #endif
144
145 #if ENABLE(ENCRYPTED_MEDIA_V2)
146 #include "CDM.h"
147 #include "MockCDM.h"
148 #endif
149
150 #if ENABLE(VIDEO_TRACK)
151 #include "CaptionUserPreferences.h"
152 #include "PageGroup.h"
153 #endif
154
155 #if ENABLE(VIDEO)
156 #include "HTMLMediaElement.h"
157 #include "TimeRanges.h"
158 #endif
159
160 #if ENABLE(SPEECH_SYNTHESIS)
161 #include "DOMWindowSpeechSynthesis.h"
162 #include "PlatformSpeechSynthesizerMock.h"
163 #include "SpeechSynthesis.h"
164 #endif
165
166 #if ENABLE(VIBRATION)
167 #include "Vibration.h"
168 #endif
169
170 #if ENABLE(MEDIA_STREAM)
171 #include "MockRealtimeMediaSourceCenter.h"
172 #include "RTCPeerConnection.h"
173 #include "RTCPeerConnectionHandlerMock.h"
174 #include "UserMediaClientMock.h"
175 #endif
176
177 #if ENABLE(MEDIA_SOURCE)
178 #include "MockMediaPlayerMediaSource.h"
179 #endif
180
181 #if PLATFORM(MAC)
182 #include "DictionaryLookup.h"
183 #endif
184
185 #if ENABLE(CONTENT_FILTERING)
186 #include "MockContentFilter.h"
187 #endif
188
189 #if ENABLE(WEB_AUDIO)
190 #include "AudioContext.h"
191 #endif
192
193 #if ENABLE(MEDIA_SESSION)
194 #include "MediaSession.h"
195 #include "MediaSessionManager.h"
196 #endif
197
198 using JSC::CodeBlock;
199 using JSC::FunctionExecutable;
200 using JSC::JSFunction;
201 using JSC::JSValue;
202 using JSC::ScriptExecutable;
203 using JSC::StackVisitor;
204
205 using namespace Inspector;
206
207 namespace WebCore {
208
209 using namespace HTMLNames;
210
211 class InspectorFrontendClientDummy : public InspectorFrontendClientLocal {
212 public:
213     InspectorFrontendClientDummy(InspectorController*, Page*);
214     virtual ~InspectorFrontendClientDummy() { }
215     virtual void attachWindow(DockSide) override { }
216     virtual void detachWindow() override { }
217
218     virtual String localizedStringsURL() override { return String(); }
219
220     virtual void bringToFront() override { }
221     virtual void closeWindow() override { }
222
223     virtual void inspectedURLChanged(const String&) override { }
224
225 protected:
226     virtual void setAttachedWindowHeight(unsigned) override { }
227     virtual void setAttachedWindowWidth(unsigned) override { }
228     virtual void setToolbarHeight(unsigned) override { }
229 };
230
231 InspectorFrontendClientDummy::InspectorFrontendClientDummy(InspectorController* controller, Page* page)
232     : InspectorFrontendClientLocal(controller, page, std::make_unique<InspectorFrontendClientLocal::Settings>())
233 {
234 }
235
236 class InspectorFrontendChannelDummy : public InspectorFrontendChannel {
237 public:
238     explicit InspectorFrontendChannelDummy(Page*);
239     virtual ~InspectorFrontendChannelDummy() { }
240     virtual bool sendMessageToFrontend(const String& message) override;
241
242 private:
243     Page* m_frontendPage;
244 };
245
246 InspectorFrontendChannelDummy::InspectorFrontendChannelDummy(Page* page)
247     : m_frontendPage(page)
248 {
249 }
250
251 bool InspectorFrontendChannelDummy::sendMessageToFrontend(const String& message)
252 {
253     return InspectorClient::doDispatchMessageOnFrontendPage(m_frontendPage, message);
254 }
255
256 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
257 {
258     if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
259         result = DocumentMarker::AllMarkers();
260     else if (equalIgnoringCase(markerType, "Spelling"))
261         result =  DocumentMarker::Spelling;
262     else if (equalIgnoringCase(markerType, "Grammar"))
263         result =  DocumentMarker::Grammar;
264     else if (equalIgnoringCase(markerType, "TextMatch"))
265         result =  DocumentMarker::TextMatch;
266     else if (equalIgnoringCase(markerType, "Replacement"))
267         result =  DocumentMarker::Replacement;
268     else if (equalIgnoringCase(markerType, "CorrectionIndicator"))
269         result =  DocumentMarker::CorrectionIndicator;
270     else if (equalIgnoringCase(markerType, "RejectedCorrection"))
271         result =  DocumentMarker::RejectedCorrection;
272     else if (equalIgnoringCase(markerType, "Autocorrected"))
273         result =  DocumentMarker::Autocorrected;
274     else if (equalIgnoringCase(markerType, "SpellCheckingExemption"))
275         result =  DocumentMarker::SpellCheckingExemption;
276     else if (equalIgnoringCase(markerType, "DeletedAutocorrection"))
277         result =  DocumentMarker::DeletedAutocorrection;
278     else if (equalIgnoringCase(markerType, "DictationAlternatives"))
279         result =  DocumentMarker::DictationAlternatives;
280 #if ENABLE(TELEPHONE_NUMBER_DETECTION)
281     else if (equalIgnoringCase(markerType, "TelephoneNumber"))
282         result =  DocumentMarker::TelephoneNumber;
283 #endif
284     else
285         return false;
286
287     return true;
288 }
289
290 const char* Internals::internalsId = "internals";
291
292 PassRefPtr<Internals> Internals::create(Document* document)
293 {
294     return adoptRef(new Internals(document));
295 }
296
297 Internals::~Internals()
298 {
299 }
300
301 void Internals::resetToConsistentState(Page* page)
302 {
303     ASSERT(page);
304
305     page->setPageScaleFactor(1, IntPoint(0, 0));
306     page->setPagination(Pagination());
307
308     FrameView* mainFrameView = page->mainFrame().view();
309     if (mainFrameView) {
310         mainFrameView->setHeaderHeight(0);
311         mainFrameView->setFooterHeight(0);
312         page->setTopContentInset(0);
313         mainFrameView->setUseFixedLayout(false);
314         mainFrameView->setFixedLayoutSize(IntSize());
315     }
316
317     TextRun::setAllowsRoundingHacks(false);
318     WebCore::overrideUserPreferredLanguages(Vector<String>());
319     WebCore::Settings::setUsesOverlayScrollbars(false);
320     page->inspectorController().setProfilerEnabled(false);
321 #if ENABLE(VIDEO_TRACK)
322     page->group().captionPreferences()->setCaptionsStyleSheetOverride(emptyString());
323     page->group().captionPreferences()->setTestingMode(false);
324 #endif
325     if (!page->mainFrame().editor().isContinuousSpellCheckingEnabled())
326         page->mainFrame().editor().toggleContinuousSpellChecking();
327     if (page->mainFrame().editor().isOverwriteModeEnabled())
328         page->mainFrame().editor().toggleOverwriteModeEnabled();
329     page->mainFrame().loader().clearTestingOverrides();
330     ApplicationCacheStorage::singleton().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
331 #if ENABLE(VIDEO)
332     PlatformMediaSessionManager::sharedManager().resetRestrictions();
333 #endif
334 #if HAVE(ACCESSIBILITY)
335     AXObjectCache::setEnhancedUserInterfaceAccessibility(false);
336     AXObjectCache::disableAccessibility();
337 #endif
338
339     MockPageOverlayClient::singleton().uninstallAllOverlays();
340
341 #if ENABLE(CONTENT_FILTERING)
342     MockContentFilterSettings::reset();
343 #endif
344 }
345
346 Internals::Internals(Document* document)
347     : ContextDestructionObserver(document)
348 {
349 #if ENABLE(VIDEO_TRACK)
350     if (document && document->page())
351         document->page()->group().captionPreferences()->setTestingMode(true);
352 #endif
353
354 #if ENABLE(MEDIA_STREAM)
355     MockRealtimeMediaSourceCenter::registerMockRealtimeMediaSourceCenter();
356     enableMockRTCPeerConnectionHandler();
357     WebCore::provideUserMediaTo(document->page(), new UserMediaClientMock());
358 #endif
359
360 #if ENABLE(CONTENT_FILTERING)
361     MockContentFilter::ensureInstalled();
362 #endif
363 }
364
365 Document* Internals::contextDocument() const
366 {
367     return downcast<Document>(scriptExecutionContext());
368 }
369
370 Frame* Internals::frame() const
371 {
372     if (!contextDocument())
373         return nullptr;
374     return contextDocument()->frame();
375 }
376
377 InternalSettings* Internals::settings() const
378 {
379     Document* document = contextDocument();
380     if (!document)
381         return 0;
382     Page* page = document->page();
383     if (!page)
384         return 0;
385     return InternalSettings::from(page);
386 }
387
388 unsigned Internals::workerThreadCount() const
389 {
390     return WorkerThread::workerThreadCount();
391 }
392
393 String Internals::address(Node* node)
394 {
395     return String::format("%p", node);
396 }
397
398 bool Internals::nodeNeedsStyleRecalc(Node* node, ExceptionCode& exception)
399 {
400     if (!node) {
401         exception = INVALID_ACCESS_ERR;
402         return false;
403     }
404
405     return node->needsStyleRecalc();
406 }
407
408 String Internals::description(Deprecated::ScriptValue value)
409 {
410     return toString(value.jsValue());
411 }
412
413 bool Internals::isPreloaded(const String& url)
414 {
415     Document* document = contextDocument();
416     return document->cachedResourceLoader().isPreloaded(url);
417 }
418
419 bool Internals::isLoadingFromMemoryCache(const String& url)
420 {
421     if (!contextDocument() || !contextDocument()->page())
422         return false;
423
424     ResourceRequest request(contextDocument()->completeURL(url));
425 #if ENABLE(CACHE_PARTITIONING)
426     request.setDomainForCachePartition(contextDocument()->topOrigin()->domainForCachePartition());
427 #endif
428     CachedResource* resource = MemoryCache::singleton().resourceForRequest(request, contextDocument()->page()->sessionID());
429     return resource && resource->status() == CachedResource::Cached;
430 }
431
432 String Internals::xhrResponseSource(XMLHttpRequest* xhr)
433 {
434     if (!xhr)
435         return "Null xhr";
436     if (xhr->resourceResponse().isNull())
437         return "Null response";
438     switch (xhr->resourceResponse().source()) {
439     case ResourceResponse::Source::Unknown:
440         return "Unknown";
441     case ResourceResponse::Source::Network:
442         return "Network";
443     case ResourceResponse::Source::DiskCache:
444         return "Disk cache";
445     case ResourceResponse::Source::DiskCacheAfterValidation:
446         return "Disk cache after validation";
447     }
448     ASSERT_NOT_REACHED();
449     return "Error";
450 }
451
452 bool Internals::isSharingStyleSheetContents(Element* a, Element* b)
453 {
454     if (!is<HTMLLinkElement>(a) || !is<HTMLLinkElement>(b))
455         return false;
456     auto& aLink = downcast<HTMLLinkElement>(*a);
457     auto& bLink = downcast<HTMLLinkElement>(*b);
458     if (!aLink.sheet() || !bLink.sheet())
459         return false;
460     return &aLink.sheet()->contents() == &bLink.sheet()->contents();
461 }
462
463 bool Internals::isStyleSheetLoadingSubresources(Element* link)
464 {
465     if (!is<HTMLLinkElement>(link))
466         return false;
467     auto& linkElement = downcast<HTMLLinkElement>(*link);
468     return linkElement.sheet() && linkElement.sheet()->contents().isLoadingSubresources();
469 }
470
471 static ResourceRequestCachePolicy stringToResourceRequestCachePolicy(const String& policy)
472 {
473     if (policy == "UseProtocolCachePolicy")
474         return UseProtocolCachePolicy;
475     if (policy == "ReloadIgnoringCacheData")
476         return ReloadIgnoringCacheData;
477     if (policy == "ReturnCacheDataElseLoad")
478         return ReturnCacheDataElseLoad;
479     if (policy == "ReturnCacheDataDontLoad")
480         return ReturnCacheDataDontLoad;
481     ASSERT_NOT_REACHED();
482     return UseProtocolCachePolicy;
483 }
484
485 void Internals::setOverrideCachePolicy(const String& policy)
486 {
487     frame()->loader().setOverrideCachePolicyForTesting(stringToResourceRequestCachePolicy(policy));
488 }
489
490 static ResourceLoadPriority stringToResourceLoadPriority(const String& policy)
491 {
492     if (policy == "ResourceLoadPriorityVeryLow")
493         return ResourceLoadPriority::VeryLow;
494     if (policy == "ResourceLoadPriorityLow")
495         return ResourceLoadPriority::Low;
496     if (policy == "ResourceLoadPriorityMedium")
497         return ResourceLoadPriority::Medium;
498     if (policy == "ResourceLoadPriorityHigh")
499         return ResourceLoadPriority::High;
500     if (policy == "ResourceLoadPriorityVeryHigh")
501         return ResourceLoadPriority::VeryHigh;
502     ASSERT_NOT_REACHED();
503     return ResourceLoadPriority::Low;
504 }
505
506 void Internals::setOverrideResourceLoadPriority(const String& priority)
507 {
508     frame()->loader().setOverrideResourceLoadPriorityForTesting(stringToResourceLoadPriority(priority));
509 }
510
511 void Internals::clearMemoryCache()
512 {
513     MemoryCache::singleton().evictResources();
514 }
515
516 void Internals::pruneMemoryCacheToSize(unsigned size)
517 {
518     MemoryCache::singleton().pruneDeadResourcesToSize(size);
519     MemoryCache::singleton().pruneLiveResourcesToSize(size, true);
520 }
521
522 unsigned Internals::memoryCacheSize() const
523 {
524     return MemoryCache::singleton().size();
525 }
526
527 void Internals::clearPageCache()
528 {
529     PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
530 }
531
532 unsigned Internals::pageCacheSize() const
533 {
534     return PageCache::singleton().pageCount();
535 }
536
537 Node* Internals::treeScopeRootNode(Node* node, ExceptionCode& ec)
538 {
539     if (!node) {
540         ec = INVALID_ACCESS_ERR;
541         return nullptr;
542     }
543
544     return &node->treeScope().rootNode();
545 }
546
547 Node* Internals::parentTreeScope(Node* node, ExceptionCode& ec)
548 {
549     if (!node) {
550         ec = INVALID_ACCESS_ERR;
551         return nullptr;
552     }
553     const TreeScope* parentTreeScope = node->treeScope().parentTreeScope();
554     return parentTreeScope ? &parentTreeScope->rootNode() : nullptr;
555 }
556
557 unsigned Internals::lastSpatialNavigationCandidateCount(ExceptionCode& ec) const
558 {
559     if (!contextDocument() || !contextDocument()->page()) {
560         ec = INVALID_ACCESS_ERR;
561         return 0;
562     }
563
564     return contextDocument()->page()->lastSpatialNavigationCandidateCount();
565 }
566
567 unsigned Internals::numberOfActiveAnimations() const
568 {
569     return frame()->animation().numberOfActiveAnimations(frame()->document());
570 }
571
572 bool Internals::animationsAreSuspended(ExceptionCode& ec) const
573 {
574     Document* document = contextDocument();
575     if (!document || !document->frame()) {
576         ec = INVALID_ACCESS_ERR;
577         return false;
578     }
579
580     return document->frame()->animation().isSuspended();
581 }
582
583 void Internals::suspendAnimations(ExceptionCode& ec) const
584 {
585     Document* document = contextDocument();
586     if (!document || !document->frame()) {
587         ec = INVALID_ACCESS_ERR;
588         return;
589     }
590
591     document->frame()->animation().suspendAnimations();
592 }
593
594 void Internals::resumeAnimations(ExceptionCode& ec) const
595 {
596     Document* document = contextDocument();
597     if (!document || !document->frame()) {
598         ec = INVALID_ACCESS_ERR;
599         return;
600     }
601
602     document->frame()->animation().resumeAnimations();
603 }
604
605 bool Internals::pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element* element, ExceptionCode& ec)
606 {
607     if (!element || pauseTime < 0) {
608         ec = INVALID_ACCESS_ERR;
609         return false;
610     }
611     return frame()->animation().pauseAnimationAtTime(element->renderer(), AtomicString(animationName), pauseTime);
612 }
613
614 bool Internals::pauseAnimationAtTimeOnPseudoElement(const String& animationName, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec)
615 {
616     if (!element || pauseTime < 0) {
617         ec = INVALID_ACCESS_ERR;
618         return false;
619     }
620
621     if (pseudoId != "before" && pseudoId != "after") {
622         ec = INVALID_ACCESS_ERR;
623         return false;
624     }
625
626     PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement();
627     if (!pseudoElement) {
628         ec = INVALID_ACCESS_ERR;
629         return false;
630     }
631
632     return frame()->animation().pauseAnimationAtTime(pseudoElement->renderer(), AtomicString(animationName), pauseTime);
633 }
634
635 bool Internals::pauseTransitionAtTimeOnElement(const String& propertyName, double pauseTime, Element* element, ExceptionCode& ec)
636 {
637     if (!element || pauseTime < 0) {
638         ec = INVALID_ACCESS_ERR;
639         return false;
640     }
641     return frame()->animation().pauseTransitionAtTime(element->renderer(), propertyName, pauseTime);
642 }
643
644 bool Internals::pauseTransitionAtTimeOnPseudoElement(const String& property, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec)
645 {
646     if (!element || pauseTime < 0) {
647         ec = INVALID_ACCESS_ERR;
648         return false;
649     }
650
651     if (pseudoId != "before" && pseudoId != "after") {
652         ec = INVALID_ACCESS_ERR;
653         return false;
654     }
655
656     PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement();
657     if (!pseudoElement) {
658         ec = INVALID_ACCESS_ERR;
659         return false;
660     }
661
662     return frame()->animation().pauseTransitionAtTime(pseudoElement->renderer(), property, pauseTime);
663 }
664
665 // FIXME: Remove.
666 bool Internals::attached(Node* node, ExceptionCode& ec)
667 {
668     if (!node) {
669         ec = INVALID_ACCESS_ERR;
670         return false;
671     }
672
673     return true;
674 }
675
676 String Internals::elementRenderTreeAsText(Element* element, ExceptionCode& ec)
677 {
678     if (!element) {
679         ec = INVALID_ACCESS_ERR;
680         return String();
681     }
682
683     element->document().updateStyleIfNeeded();
684
685     String representation = externalRepresentation(element);
686     if (representation.isEmpty()) {
687         ec = INVALID_ACCESS_ERR;
688         return String();
689     }
690
691     return representation;
692 }
693
694 bool Internals::hasPausedImageAnimations(Element* element, ExceptionCode& ec)
695 {
696     if (!element) {
697         ec = INVALID_ACCESS_ERR;
698         return false;
699     }
700     return element->renderer() && element->renderer()->hasPausedImageAnimations();
701 }
702
703 PassRefPtr<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node* node, ExceptionCode& ec) const
704 {
705     if (!node) {
706         ec = INVALID_ACCESS_ERR;
707         return 0;
708     }
709
710     bool allowVisitedStyle = true;
711     return CSSComputedStyleDeclaration::create(node, allowVisitedStyle);
712 }
713
714 Node* Internals::ensureShadowRoot(Element* host, ExceptionCode& ec)
715 {
716     if (!host) {
717         ec = INVALID_ACCESS_ERR;
718         return 0;
719     }
720
721     if (ShadowRoot* shadowRoot = host->shadowRoot())
722         return shadowRoot;
723
724     return host->createShadowRoot(ec).get();
725 }
726
727 Node* Internals::ensureUserAgentShadowRoot(Element* host, ExceptionCode& ec)
728 {
729     if (!host) {
730         ec = INVALID_ACCESS_ERR;
731         return nullptr;
732     }
733     return &host->ensureUserAgentShadowRoot();
734 }
735
736 Node* Internals::createShadowRoot(Element* host, ExceptionCode& ec)
737 {
738     if (!host) {
739         ec = INVALID_ACCESS_ERR;
740         return 0;
741     }
742     return host->createShadowRoot(ec).get();
743 }
744
745 Node* Internals::shadowRoot(Element* host, ExceptionCode& ec)
746 {
747     if (!host) {
748         ec = INVALID_ACCESS_ERR;
749         return nullptr;
750     }
751     return host->shadowRoot();
752 }
753
754 String Internals::shadowRootType(const Node* root, ExceptionCode& ec) const
755 {
756     if (!is<ShadowRoot>(root)) {
757         ec = INVALID_ACCESS_ERR;
758         return String();
759     }
760
761     switch (downcast<ShadowRoot>(*root).type()) {
762     case ShadowRoot::UserAgentShadowRoot:
763         return String("UserAgentShadowRoot");
764     default:
765         ASSERT_NOT_REACHED();
766         return String("Unknown");
767     }
768 }
769
770 Element* Internals::includerFor(Node*, ExceptionCode& ec)
771 {
772     ec = INVALID_ACCESS_ERR;
773     return nullptr;
774 }
775
776 String Internals::shadowPseudoId(Element* element, ExceptionCode& ec)
777 {
778     if (!element) {
779         ec = INVALID_ACCESS_ERR;
780         return String();
781     }
782
783     return element->shadowPseudoId().string();
784 }
785
786 void Internals::setShadowPseudoId(Element* element, const String& id, ExceptionCode& ec)
787 {
788     if (!element) {
789         ec = INVALID_ACCESS_ERR;
790         return;
791     }
792
793     return element->setPseudo(id);
794 }
795
796 bool Internals::isTimerThrottled(int timeoutId, ExceptionCode& ec)
797 {
798     DOMTimer* timer = scriptExecutionContext()->findTimeout(timeoutId);
799     if (!timer) {
800         ec = NOT_FOUND_ERR;
801         return false;
802     }
803     return timer->m_throttleState == DOMTimer::ShouldThrottle;
804 }
805
806 bool Internals::isRequestAnimationFrameThrottled() const
807 {
808 #if ENABLE(REQUEST_ANIMATION_FRAME)
809     auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
810     if (!scriptedAnimationController)
811         return false;
812     return scriptedAnimationController->isThrottled();
813 #else
814     return false;
815 #endif
816 }
817
818 bool Internals::areTimersThrottled() const
819 {
820     return contextDocument()->isTimerThrottlingEnabled();
821 }
822
823 String Internals::visiblePlaceholder(Element* element)
824 {
825     if (is<HTMLTextFormControlElement>(element)) {
826         const HTMLTextFormControlElement& textFormControlElement = downcast<HTMLTextFormControlElement>(*element);
827         if (!textFormControlElement.isPlaceholderVisible())
828             return String();
829         if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
830             return placeholderElement->textContent();
831     }
832
833     return String();
834 }
835
836 #if ENABLE(INPUT_TYPE_COLOR)
837 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
838 {
839     if (!is<HTMLInputElement>(*element))
840         return;
841     HTMLInputElement* inputElement = element->toInputElement();
842     if (!inputElement)
843         return;
844     inputElement->selectColorInColorChooser(Color(colorValue));
845 }
846 #endif
847
848 Vector<String> Internals::formControlStateOfPreviousHistoryItem(ExceptionCode& ec)
849 {
850     HistoryItem* mainItem = frame()->loader().history().previousItem();
851     if (!mainItem) {
852         ec = INVALID_ACCESS_ERR;
853         return Vector<String>();
854     }
855     String uniqueName = frame()->tree().uniqueName();
856     if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) {
857         ec = INVALID_ACCESS_ERR;
858         return Vector<String>();
859     }
860     return mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState();
861 }
862
863 void Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state, ExceptionCode& ec)
864 {
865     HistoryItem* mainItem = frame()->loader().history().previousItem();
866     if (!mainItem) {
867         ec = INVALID_ACCESS_ERR;
868         return;
869     }
870     String uniqueName = frame()->tree().uniqueName();
871     if (mainItem->target() == uniqueName)
872         mainItem->setDocumentState(state);
873     else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
874         subItem->setDocumentState(state);
875     else
876         ec = INVALID_ACCESS_ERR;
877 }
878
879 #if ENABLE(SPEECH_SYNTHESIS)
880 void Internals::enableMockSpeechSynthesizer()
881 {
882     Document* document = contextDocument();
883     if (!document || !document->domWindow())
884         return;
885     SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(document->domWindow());
886     if (!synthesis)
887         return;
888     
889     synthesis->setPlatformSynthesizer(std::make_unique<PlatformSpeechSynthesizerMock>(synthesis));
890 }
891 #endif
892
893 #if ENABLE(MEDIA_STREAM)
894 void Internals::enableMockRTCPeerConnectionHandler()
895 {
896     RTCPeerConnectionHandler::create = RTCPeerConnectionHandlerMock::create;
897 }
898 #endif
899
900 Ref<ClientRect> Internals::absoluteCaretBounds(ExceptionCode& ec)
901 {
902     Document* document = contextDocument();
903     if (!document || !document->frame()) {
904         ec = INVALID_ACCESS_ERR;
905         return ClientRect::create();
906     }
907
908     return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
909 }
910
911 Ref<ClientRect> Internals::boundingBox(Element* element, ExceptionCode& ec)
912 {
913     if (!element) {
914         ec = INVALID_ACCESS_ERR;
915         return ClientRect::create();
916     }
917
918     element->document().updateLayoutIgnorePendingStylesheets();
919     auto renderer = element->renderer();
920     if (!renderer)
921         return ClientRect::create();
922     return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
923 }
924
925 Ref<ClientRectList> Internals::inspectorHighlightRects(ExceptionCode& ec)
926 {
927     Document* document = contextDocument();
928     if (!document || !document->page()) {
929         ec = INVALID_ACCESS_ERR;
930         return ClientRectList::create();
931     }
932
933     Highlight highlight;
934     document->page()->inspectorController().getHighlight(highlight, InspectorOverlay::CoordinateSystem::View);
935     return ClientRectList::create(highlight.quads);
936 }
937
938 String Internals::inspectorHighlightObject(ExceptionCode& ec)
939 {
940     Document* document = contextDocument();
941     if (!document || !document->page()) {
942         ec = INVALID_ACCESS_ERR;
943         return String();
944     }
945
946     return document->page()->inspectorController().buildObjectForHighlightedNodes()->toJSONString();
947 }
948
949 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionCode& ec)
950 {
951     if (!node) {
952         ec = INVALID_ACCESS_ERR;
953         return 0;
954     }
955
956     DocumentMarker::MarkerTypes markerTypes = 0;
957     if (!markerTypesFrom(markerType, markerTypes)) {
958         ec = SYNTAX_ERR;
959         return 0;
960     }
961
962     node->document().frame()->editor().updateEditorUINowIfScheduled();
963
964     return node->document().markers().markersFor(node, markerTypes).size();
965 }
966
967 RenderedDocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
968 {
969     node->document().updateLayoutIgnorePendingStylesheets();
970     if (!node) {
971         ec = INVALID_ACCESS_ERR;
972         return nullptr;
973     }
974
975     DocumentMarker::MarkerTypes markerTypes = 0;
976     if (!markerTypesFrom(markerType, markerTypes)) {
977         ec = SYNTAX_ERR;
978         return nullptr;
979     }
980
981     node->document().frame()->editor().updateEditorUINowIfScheduled();
982
983     Vector<RenderedDocumentMarker*> markers = node->document().markers().markersFor(node, markerTypes);
984     if (markers.size() <= index)
985         return nullptr;
986     return markers[index];
987 }
988
989 PassRefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
990 {
991     RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
992     if (!marker)
993         return nullptr;
994     return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
995 }
996
997 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
998 {
999     RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
1000     if (!marker)
1001         return String();
1002     return marker->description();
1003 }
1004
1005 void Internals::addTextMatchMarker(const Range* range, bool isActive)
1006 {
1007     range->ownerDocument().updateLayoutIgnorePendingStylesheets();
1008     range->ownerDocument().markers().addTextMatchMarker(range, isActive);
1009 }
1010
1011 void Internals::setMarkedTextMatchesAreHighlighted(bool flag, ExceptionCode& ec)
1012 {
1013     Document* document = contextDocument();
1014     if (!document || !document->frame()) {
1015         ec = INVALID_ACCESS_ERR;
1016         return;
1017     }
1018     document->frame()->editor().setMarkedTextMatchesAreHighlighted(flag);
1019 }
1020
1021 void Internals::invalidateFontCache()
1022 {
1023     FontCache::singleton().invalidate();
1024 }
1025
1026 void Internals::setScrollViewPosition(long x, long y, ExceptionCode& ec)
1027 {
1028     Document* document = contextDocument();
1029     if (!document || !document->view()) {
1030         ec = INVALID_ACCESS_ERR;
1031         return;
1032     }
1033
1034     FrameView* frameView = document->view();
1035     bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
1036     bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
1037
1038     frameView->setConstrainsScrollingToContentEdge(false);
1039     frameView->setScrollbarsSuppressed(false);
1040     frameView->setScrollOffsetFromInternals(IntPoint(x, y));
1041     frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
1042     frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
1043 }
1044
1045 void Internals::setViewBaseBackgroundColor(const String& colorValue, ExceptionCode& ec)
1046 {
1047     Document* document = contextDocument();
1048     if (!document || !document->view()) {
1049         ec = INVALID_ACCESS_ERR;
1050         return;
1051     }
1052
1053     document->view()->setBaseBackgroundColor(Color(colorValue));
1054 }
1055
1056 void Internals::setPagination(const String& mode, int gap, int pageLength, ExceptionCode& ec)
1057 {
1058     Document* document = contextDocument();
1059     if (!document || !document->page()) {
1060         ec = INVALID_ACCESS_ERR;
1061         return;
1062     }
1063     Page* page = document->page();
1064
1065     Pagination pagination;
1066     if (mode == "Unpaginated")
1067         pagination.mode = Pagination::Unpaginated;
1068     else if (mode == "LeftToRightPaginated")
1069         pagination.mode = Pagination::LeftToRightPaginated;
1070     else if (mode == "RightToLeftPaginated")
1071         pagination.mode = Pagination::RightToLeftPaginated;
1072     else if (mode == "TopToBottomPaginated")
1073         pagination.mode = Pagination::TopToBottomPaginated;
1074     else if (mode == "BottomToTopPaginated")
1075         pagination.mode = Pagination::BottomToTopPaginated;
1076     else {
1077         ec = SYNTAX_ERR;
1078         return;
1079     }
1080
1081     pagination.gap = gap;
1082     pagination.pageLength = pageLength;
1083     page->setPagination(pagination);
1084 }
1085
1086 String Internals::configurationForViewport(float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight, ExceptionCode& ec)
1087 {
1088     Document* document = contextDocument();
1089     if (!document || !document->page()) {
1090         ec = INVALID_ACCESS_ERR;
1091         return String();
1092     }
1093     Page* page = document->page();
1094
1095     const int defaultLayoutWidthForNonMobilePages = 980;
1096
1097     ViewportArguments arguments = page->viewportArguments();
1098     ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
1099     restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
1100     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
1101
1102     return "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");
1103 }
1104
1105 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionCode& ec)
1106 {
1107     if (!textField) {
1108         ec = INVALID_ACCESS_ERR;
1109         return false;
1110     }
1111
1112     if (HTMLInputElement* inputElement = textField->toInputElement())
1113         return inputElement->lastChangeWasUserEdit();
1114
1115     if (is<HTMLTextAreaElement>(*textField))
1116         return downcast<HTMLTextAreaElement>(*textField).lastChangeWasUserEdit();
1117
1118     ec = INVALID_NODE_TYPE_ERR;
1119     return false;
1120 }
1121
1122 bool Internals::elementShouldAutoComplete(Element* element, ExceptionCode& ec)
1123 {
1124     if (!element) {
1125         ec = INVALID_ACCESS_ERR;
1126         return false;
1127     }
1128
1129     if (HTMLInputElement* inputElement = element->toInputElement())
1130         return inputElement->shouldAutocomplete();
1131
1132     ec = INVALID_NODE_TYPE_ERR;
1133     return false;
1134 }
1135
1136 void Internals::setEditingValue(Element* element, const String& value, ExceptionCode& ec)
1137 {
1138     if (!element) {
1139         ec = INVALID_ACCESS_ERR;
1140         return;
1141     }
1142
1143     HTMLInputElement* inputElement = element->toInputElement();
1144     if (!inputElement) {
1145         ec = INVALID_NODE_TYPE_ERR;
1146         return;
1147     }
1148
1149     inputElement->setEditingValue(value);
1150 }
1151
1152 void Internals::setAutofilled(Element* element, bool enabled, ExceptionCode& ec)
1153 {
1154     HTMLInputElement* inputElement = element->toInputElement();
1155     if (!inputElement) {
1156         ec = INVALID_ACCESS_ERR;
1157         return;
1158     }
1159     inputElement->setAutoFilled(enabled);
1160 }
1161
1162 void Internals::setShowAutoFillButton(Element* element, bool show, ExceptionCode& ec)
1163 {
1164     HTMLInputElement* inputElement = element->toInputElement();
1165     if (!inputElement) {
1166         ec = INVALID_ACCESS_ERR;
1167         return;
1168     }
1169     inputElement->setShowAutoFillButton(show);
1170 }
1171
1172
1173 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionCode& ec)
1174 {
1175     if (!element || !element->document().view()) {
1176         ec = INVALID_ACCESS_ERR;
1177         return;
1178     }
1179     FrameView* frameView = element->document().view();
1180     frameView->scrollElementToRect(element, IntRect(x, y, w, h));
1181 }
1182
1183 void Internals::paintControlTints(ExceptionCode& ec)
1184 {
1185     Document* document = contextDocument();
1186     if (!document || !document->view()) {
1187         ec = INVALID_ACCESS_ERR;
1188         return;
1189     }
1190
1191     FrameView* frameView = document->view();
1192     frameView->paintControlTints();
1193 }
1194
1195 PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionCode& ec)
1196 {
1197     if (!scope) {
1198         ec = INVALID_ACCESS_ERR;
1199         return 0;
1200     }
1201
1202     return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength);
1203 }
1204
1205 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1206 {
1207     if (!scope || !range) {
1208         ec = INVALID_ACCESS_ERR;
1209         return 0;
1210     }
1211
1212     size_t location = 0;
1213     size_t unusedLength = 0;
1214     TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength);
1215     return location;
1216 }
1217
1218 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1219 {
1220     if (!scope || !range) {
1221         ec = INVALID_ACCESS_ERR;
1222         return 0;
1223     }
1224
1225     size_t unusedLocation = 0;
1226     size_t length = 0;
1227     TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length);
1228     return length;
1229 }
1230
1231 String Internals::rangeAsText(const Range* range, ExceptionCode& ec)
1232 {
1233     if (!range) {
1234         ec = INVALID_ACCESS_ERR;
1235         return String();
1236     }
1237
1238     return range->text();
1239 }
1240
1241 PassRefPtr<Range> Internals::subrange(Range* range, int rangeLocation, int rangeLength, ExceptionCode& ec)
1242 {
1243     if (!range) {
1244         ec = INVALID_ACCESS_ERR;
1245         return 0;
1246     }
1247
1248     return TextIterator::subrange(range, rangeLocation, rangeLength);
1249 }
1250
1251 RefPtr<Range> Internals::rangeForDictionaryLookupAtLocation(int x, int y, ExceptionCode& ec)
1252 {
1253 #if PLATFORM(MAC)
1254     Document* document = contextDocument();
1255     if (!document || !document->frame()) {
1256         ec = INVALID_ACCESS_ERR;
1257         return nullptr;
1258     }
1259
1260     document->updateLayoutIgnorePendingStylesheets();
1261     
1262     HitTestResult result = document->frame()->mainFrame().eventHandler().hitTestResultAtPoint(IntPoint(x, y));
1263     NSDictionary *options = nullptr;
1264     return rangeForDictionaryLookupAtHitTestResult(result, &options);
1265 #else
1266     UNUSED_PARAM(x);
1267     UNUSED_PARAM(y);
1268     ec = INVALID_ACCESS_ERR;
1269     return nullptr;
1270 #endif
1271 }
1272
1273 void Internals::setDelegatesScrolling(bool enabled, ExceptionCode& ec)
1274 {
1275     Document* document = contextDocument();
1276     // Delegate scrolling is valid only on mainframe's view.
1277     if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame()) {
1278         ec = INVALID_ACCESS_ERR;
1279         return;
1280     }
1281
1282     document->view()->setDelegatesScrolling(enabled);
1283 }
1284
1285 int Internals::lastSpellCheckRequestSequence(ExceptionCode& ec)
1286 {
1287     Document* document = contextDocument();
1288     if (!document || !document->frame()) {
1289         ec = INVALID_ACCESS_ERR;
1290         return -1;
1291     }
1292
1293     return document->frame()->editor().spellChecker().lastRequestSequence();
1294 }
1295
1296 int Internals::lastSpellCheckProcessedSequence(ExceptionCode& ec)
1297 {
1298     Document* document = contextDocument();
1299     if (!document || !document->frame()) {
1300         ec = INVALID_ACCESS_ERR;
1301         return -1;
1302     }
1303
1304     return document->frame()->editor().spellChecker().lastProcessedSequence();
1305 }
1306
1307 Vector<String> Internals::userPreferredLanguages() const
1308 {
1309     return WebCore::userPreferredLanguages();
1310 }
1311
1312 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1313 {
1314     WebCore::overrideUserPreferredLanguages(languages);
1315 }
1316
1317 Vector<String> Internals::userPreferredAudioCharacteristics() const
1318 {
1319     Document* document = contextDocument();
1320     if (!document || !document->page())
1321         return Vector<String>();
1322 #if ENABLE(VIDEO_TRACK)
1323     return document->page()->group().captionPreferences()->preferredAudioCharacteristics();
1324 #else
1325     return Vector<String>();
1326 #endif
1327 }
1328
1329 void Internals::setUserPreferredAudioCharacteristic(const String& characteristic)
1330 {
1331     Document* document = contextDocument();
1332     if (!document || !document->page())
1333         return;
1334 #if ENABLE(VIDEO_TRACK)
1335     document->page()->group().captionPreferences()->setPreferredAudioCharacteristic(characteristic);
1336 #else
1337     UNUSED_PARAM(characteristic);
1338 #endif
1339 }
1340
1341 unsigned Internals::wheelEventHandlerCount(ExceptionCode& ec)
1342 {
1343     Document* document = contextDocument();
1344     if (!document) {
1345         ec = INVALID_ACCESS_ERR;
1346         return 0;
1347     }
1348
1349     return document->wheelEventHandlerCount();
1350 }
1351
1352 unsigned Internals::touchEventHandlerCount(ExceptionCode& ec)
1353 {
1354     Document* document = contextDocument();
1355     if (!document) {
1356         ec = INVALID_ACCESS_ERR;
1357         return 0;
1358     }
1359
1360     return document->touchEventHandlerCount();
1361 }
1362
1363 // FIXME: Remove the document argument. It is almost always the same as
1364 // contextDocument(), with the exception of a few tests that pass a
1365 // different document, and could just make the call through another Internals
1366 // instance instead.
1367 PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
1368     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionCode& ec) const
1369 {
1370     if (!document || !document->frame() || !document->frame()->view()) {
1371         ec = INVALID_ACCESS_ERR;
1372         return 0;
1373     }
1374
1375     Frame* frame = document->frame();
1376     FrameView* frameView = document->view();
1377     RenderView* renderView = document->renderView();
1378     if (!renderView)
1379         return 0;
1380
1381     document->updateLayoutIgnorePendingStylesheets();
1382
1383     float zoomFactor = frame->pageZoomFactor();
1384     LayoutPoint point(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY());
1385
1386     HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
1387     if (ignoreClipping)
1388         hitType |= HitTestRequest::IgnoreClipping;
1389     if (!allowShadowContent)
1390         hitType |= HitTestRequest::DisallowShadowContent;
1391     if (allowChildFrameContent)
1392         hitType |= HitTestRequest::AllowChildFrameContent;
1393
1394     HitTestRequest request(hitType);
1395
1396     // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
1397     if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
1398         return 0;
1399
1400     Vector<Ref<Node>> matches;
1401
1402     // Need padding to trigger a rect based hit test, but we want to return a NodeList
1403     // so we special case this.
1404     if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
1405         HitTestResult result(point);
1406         renderView->hitTest(request, result);
1407         if (result.innerNode())
1408             matches.append(*result.innerNode()->deprecatedShadowAncestorNode());
1409     } else {
1410         HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
1411         renderView->hitTest(request, result);
1412         
1413         const HitTestResult::NodeSet& nodeSet = result.rectBasedTestResult();
1414         matches.reserveInitialCapacity(nodeSet.size());
1415         for (auto& node : nodeSet)
1416             matches.uncheckedAppend(*node);
1417     }
1418
1419     return StaticNodeList::adopt(matches);
1420 }
1421
1422 class GetCallerCodeBlockFunctor {
1423 public:
1424     GetCallerCodeBlockFunctor()
1425         : m_iterations(0)
1426         , m_codeBlock(0)
1427     {
1428     }
1429
1430     StackVisitor::Status operator()(StackVisitor& visitor)
1431     {
1432         ++m_iterations;
1433         if (m_iterations < 2)
1434             return StackVisitor::Continue;
1435
1436         m_codeBlock = visitor->codeBlock();
1437         return StackVisitor::Done;
1438     }
1439
1440     CodeBlock* codeBlock() const { return m_codeBlock; }
1441
1442 private:
1443     int m_iterations;
1444     CodeBlock* m_codeBlock;
1445 };
1446
1447 String Internals::parserMetaData(Deprecated::ScriptValue value)
1448 {
1449     JSC::VM& vm = contextDocument()->vm();
1450     JSC::ExecState* exec = vm.topCallFrame;
1451     JSC::JSValue code = value.jsValue();
1452     ScriptExecutable* executable;
1453
1454     if (!code || code.isNull() || code.isUndefined()) {
1455         GetCallerCodeBlockFunctor iter;
1456         exec->iterate(iter);
1457         CodeBlock* codeBlock = iter.codeBlock();
1458         executable = codeBlock->ownerExecutable(); 
1459     } else if (code.isFunction()) {
1460         JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec));
1461         executable = funcObj->jsExecutable();
1462     } else
1463         return String();
1464
1465     unsigned startLine = executable->firstLine();
1466     unsigned startColumn = executable->startColumn();
1467     unsigned endLine = executable->lastLine();
1468     unsigned endColumn = executable->endColumn();
1469
1470     StringBuilder result;
1471
1472     if (executable->isFunctionExecutable()) {
1473         FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable);
1474         String inferredName = funcExecutable->inferredName().string();
1475         result.appendLiteral("function \"");
1476         result.append(inferredName);
1477         result.append('"');
1478     } else if (executable->isEvalExecutable())
1479         result.appendLiteral("eval");
1480     else {
1481         ASSERT(executable->isProgramExecutable());
1482         result.appendLiteral("program");
1483     }
1484
1485     result.appendLiteral(" { ");
1486     result.appendNumber(startLine);
1487     result.append(':');
1488     result.appendNumber(startColumn);
1489     result.appendLiteral(" - ");
1490     result.appendNumber(endLine);
1491     result.append(':');
1492     result.appendNumber(endColumn);
1493     result.appendLiteral(" }");
1494
1495     return result.toString();
1496 }
1497
1498 void Internals::setBatteryStatus(const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
1499 {
1500     Document* document = contextDocument();
1501     if (!document || !document->page()) {
1502         ec = INVALID_ACCESS_ERR;
1503         return;
1504     }
1505
1506 #if ENABLE(BATTERY_STATUS)
1507     BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
1508 #else
1509     UNUSED_PARAM(eventType);
1510     UNUSED_PARAM(charging);
1511     UNUSED_PARAM(chargingTime);
1512     UNUSED_PARAM(dischargingTime);
1513     UNUSED_PARAM(level);
1514 #endif
1515 }
1516
1517 void Internals::setDeviceProximity(const String& eventType, double value, double min, double max, ExceptionCode& ec)
1518 {
1519     Document* document = contextDocument();
1520     if (!document || !document->page()) {
1521         ec = INVALID_ACCESS_ERR;
1522         return;
1523     }
1524
1525 #if ENABLE(PROXIMITY_EVENTS)
1526     DeviceProximityController::from(document->page())->didChangeDeviceProximity(value, min, max);
1527 #else
1528     UNUSED_PARAM(eventType);
1529     UNUSED_PARAM(value);
1530     UNUSED_PARAM(min);
1531     UNUSED_PARAM(max);
1532 #endif
1533 }
1534
1535 void Internals::updateEditorUINowIfScheduled()
1536 {
1537     if (Document* document = contextDocument()) {
1538         if (Frame* frame = document->frame())
1539             frame->editor().updateEditorUINowIfScheduled();
1540     }
1541 }
1542
1543 bool Internals::hasSpellingMarker(int from, int length, ExceptionCode&)
1544 {
1545     Document* document = contextDocument();
1546     if (!document || !document->frame())
1547         return false;
1548
1549     updateEditorUINowIfScheduled();
1550
1551     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1552 }
1553     
1554 bool Internals::hasAutocorrectedMarker(int from, int length, ExceptionCode&)
1555 {
1556     Document* document = contextDocument();
1557     if (!document || !document->frame())
1558         return false;
1559
1560     updateEditorUINowIfScheduled();
1561
1562     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
1563 }
1564
1565 void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionCode&)
1566 {
1567     if (!contextDocument() || !contextDocument()->frame())
1568         return;
1569
1570     if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
1571         contextDocument()->frame()->editor().toggleContinuousSpellChecking();
1572 }
1573
1574 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled, ExceptionCode&)
1575 {
1576     if (!contextDocument() || !contextDocument()->frame())
1577         return;
1578
1579 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1580     if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
1581         contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
1582 #else
1583     UNUSED_PARAM(enabled);
1584 #endif
1585 }
1586
1587 void Internals::setAutomaticLinkDetectionEnabled(bool enabled, ExceptionCode&)
1588 {
1589     if (!contextDocument() || !contextDocument()->frame())
1590         return;
1591
1592 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1593     if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
1594         contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
1595 #else
1596     UNUSED_PARAM(enabled);
1597 #endif
1598 }
1599
1600 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled, ExceptionCode&)
1601 {
1602     if (!contextDocument() || !contextDocument()->frame())
1603         return;
1604
1605 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1606     if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
1607         contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
1608 #else
1609     UNUSED_PARAM(enabled);
1610 #endif
1611 }
1612
1613 void Internals::setAutomaticTextReplacementEnabled(bool enabled, ExceptionCode&)
1614 {
1615     if (!contextDocument() || !contextDocument()->frame())
1616         return;
1617
1618 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1619     if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
1620         contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
1621 #else
1622     UNUSED_PARAM(enabled);
1623 #endif
1624 }
1625
1626 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled, ExceptionCode&)
1627 {
1628     if (!contextDocument() || !contextDocument()->frame())
1629         return;
1630
1631 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1632     if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
1633         contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
1634 #else
1635     UNUSED_PARAM(enabled);
1636 #endif
1637 }
1638
1639 bool Internals::isOverwriteModeEnabled(ExceptionCode&)
1640 {
1641     Document* document = contextDocument();
1642     if (!document || !document->frame())
1643         return false;
1644
1645     return document->frame()->editor().isOverwriteModeEnabled();
1646 }
1647
1648 void Internals::toggleOverwriteModeEnabled(ExceptionCode&)
1649 {
1650     Document* document = contextDocument();
1651     if (!document || !document->frame())
1652         return;
1653
1654     document->frame()->editor().toggleOverwriteModeEnabled();
1655 }
1656
1657 unsigned Internals::countMatchesForText(const String& text, unsigned findOptions, const String& markMatches, ExceptionCode&)
1658 {
1659     Document* document = contextDocument();
1660     if (!document || !document->frame())
1661         return 0;
1662
1663     bool mark = markMatches == "mark";
1664     return document->frame()->editor().countMatchesForText(text, nullptr, findOptions, 1000, mark, nullptr);
1665 }
1666
1667 const ProfilesArray& Internals::consoleProfiles() const
1668 {
1669     return contextDocument()->page()->console().profiles();
1670 }
1671
1672 unsigned Internals::numberOfLiveNodes() const
1673 {
1674     unsigned nodeCount = 0;
1675     for (auto* document : Document::allDocuments())
1676         nodeCount += document->referencingNodeCount();
1677     return nodeCount;
1678 }
1679
1680 unsigned Internals::numberOfLiveDocuments() const
1681 {
1682     return Document::allDocuments().size();
1683 }
1684
1685 Vector<String> Internals::consoleMessageArgumentCounts() const
1686 {
1687     Document* document = contextDocument();
1688     if (!document || !document->page())
1689         return Vector<String>();
1690
1691     InstrumentingAgents* instrumentingAgents = InspectorInstrumentation::instrumentingAgentsForPage(document->page());
1692     if (!instrumentingAgents)
1693         return Vector<String>();
1694
1695     InspectorConsoleAgent* consoleAgent = instrumentingAgents->webConsoleAgent();
1696     if (!consoleAgent)
1697         return Vector<String>();
1698
1699     Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
1700     Vector<String> result(counts.size());
1701     for (size_t i = 0; i < counts.size(); i++)
1702         result[i] = String::number(counts[i]);
1703     return result;
1704 }
1705
1706 PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
1707 {
1708     Page* page = contextDocument()->frame()->page();
1709     ASSERT(page);
1710
1711     DOMWindow* window = page->mainFrame().document()->domWindow();
1712     ASSERT(window);
1713
1714     m_frontendWindow = window->open(url, "", "", *window, *window);
1715     ASSERT(m_frontendWindow);
1716
1717     Page* frontendPage = m_frontendWindow->document()->page();
1718     ASSERT(frontendPage);
1719
1720     m_frontendClient = std::make_unique<InspectorFrontendClientDummy>(&page->inspectorController(), frontendPage);
1721     frontendPage->inspectorController().setInspectorFrontendClient(m_frontendClient.get());
1722
1723     bool isAutomaticInspection = false;
1724     m_frontendChannel = std::make_unique<InspectorFrontendChannelDummy>(frontendPage);
1725     page->inspectorController().connectFrontend(m_frontendChannel.get(), isAutomaticInspection);
1726
1727     return m_frontendWindow;
1728 }
1729
1730 void Internals::closeDummyInspectorFrontend()
1731 {
1732     Page* page = contextDocument()->frame()->page();
1733     ASSERT(page);
1734     ASSERT(m_frontendWindow);
1735
1736     page->inspectorController().disconnectFrontend(Inspector::DisconnectReason::InspectorDestroyed);
1737
1738     m_frontendClient = nullptr;
1739     m_frontendChannel = nullptr;
1740
1741     m_frontendWindow->close(m_frontendWindow->scriptExecutionContext());
1742     m_frontendWindow = nullptr;
1743 }
1744
1745 void Internals::setJavaScriptProfilingEnabled(bool enabled, ExceptionCode& ec)
1746 {
1747     Page* page = contextDocument()->frame()->page();
1748     if (!page) {
1749         ec = INVALID_ACCESS_ERR;
1750         return;
1751     }
1752
1753     page->inspectorController().setProfilerEnabled(enabled);
1754 }
1755
1756 void Internals::setInspectorIsUnderTest(bool isUnderTest, ExceptionCode& ec)
1757 {
1758     Page* page = contextDocument()->frame()->page();
1759     if (!page) {
1760         ec = INVALID_ACCESS_ERR;
1761         return;
1762     }
1763
1764     page->inspectorController().setIsUnderTest(isUnderTest);
1765 }
1766
1767 bool Internals::hasGrammarMarker(int from, int length, ExceptionCode&)
1768 {
1769     Document* document = contextDocument();
1770     if (!document || !document->frame())
1771         return false;
1772
1773     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1774 }
1775
1776 unsigned Internals::numberOfScrollableAreas(ExceptionCode&)
1777 {
1778     Document* document = contextDocument();
1779     if (!document || !document->frame())
1780         return 0;
1781
1782     unsigned count = 0;
1783     Frame* frame = document->frame();
1784     if (frame->view()->scrollableAreas())
1785         count += frame->view()->scrollableAreas()->size();
1786
1787     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1788         if (child->view() && child->view()->scrollableAreas())
1789             count += child->view()->scrollableAreas()->size();
1790     }
1791
1792     return count;
1793 }
1794     
1795 bool Internals::isPageBoxVisible(int pageNumber, ExceptionCode& ec)
1796 {
1797     Document* document = contextDocument();
1798     if (!document) {
1799         ec = INVALID_ACCESS_ERR;
1800         return false;
1801     }
1802
1803     return document->isPageBoxVisible(pageNumber);
1804 }
1805
1806 // FIXME: Remove the document argument. It is almost always the same as
1807 // contextDocument(), with the exception of a few tests that pass a
1808 // different document, and could just make the call through another Internals
1809 // instance instead.
1810 String Internals::layerTreeAsText(Document* document, ExceptionCode& ec) const
1811 {
1812     return layerTreeAsText(document, 0, ec);
1813 }
1814
1815 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionCode& ec) const
1816 {
1817     if (!document || !document->frame()) {
1818         ec = INVALID_ACCESS_ERR;
1819         return String();
1820     }
1821
1822     LayerTreeFlags layerTreeFlags = 0;
1823     if (flags & LAYER_TREE_INCLUDES_VISIBLE_RECTS)
1824         layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
1825     if (flags & LAYER_TREE_INCLUDES_TILE_CACHES)
1826         layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
1827     if (flags & LAYER_TREE_INCLUDES_REPAINT_RECTS)
1828         layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
1829     if (flags & LAYER_TREE_INCLUDES_PAINTING_PHASES)
1830         layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
1831     if (flags & LAYER_TREE_INCLUDES_CONTENT_LAYERS)
1832         layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
1833
1834     return document->frame()->layerTreeAsText(layerTreeFlags);
1835 }
1836
1837 String Internals::repaintRectsAsText(ExceptionCode& ec) const
1838 {
1839     Document* document = contextDocument();
1840     if (!document || !document->frame()) {
1841         ec = INVALID_ACCESS_ERR;
1842         return String();
1843     }
1844
1845     return document->frame()->trackedRepaintRectsAsText();
1846 }
1847
1848 String Internals::scrollingStateTreeAsText(ExceptionCode& ec) const
1849 {
1850     Document* document = contextDocument();
1851     if (!document || !document->frame()) {
1852         ec = INVALID_ACCESS_ERR;
1853         return String();
1854     }
1855
1856     Page* page = document->page();
1857     if (!page)
1858         return String();
1859
1860     return page->scrollingStateTreeAsText();
1861 }
1862
1863 String Internals::mainThreadScrollingReasons(ExceptionCode& ec) const
1864 {
1865     Document* document = contextDocument();
1866     if (!document || !document->frame()) {
1867         ec = INVALID_ACCESS_ERR;
1868         return String();
1869     }
1870
1871     Page* page = document->page();
1872     if (!page)
1873         return String();
1874
1875     return page->synchronousScrollingReasonsAsText();
1876 }
1877
1878 RefPtr<ClientRectList> Internals::nonFastScrollableRects(ExceptionCode& ec) const
1879 {
1880     Document* document = contextDocument();
1881     if (!document || !document->frame()) {
1882         ec = INVALID_ACCESS_ERR;
1883         return nullptr;
1884     }
1885
1886     Page* page = document->page();
1887     if (!page)
1888         return nullptr;
1889
1890     return page->nonFastScrollableRects();
1891 }
1892
1893 void Internals::garbageCollectDocumentResources(ExceptionCode& ec) const
1894 {
1895     Document* document = contextDocument();
1896     if (!document) {
1897         ec = INVALID_ACCESS_ERR;
1898         return;
1899     }
1900     document->cachedResourceLoader().garbageCollectDocumentResources();
1901 }
1902
1903 void Internals::allowRoundingHacks() const
1904 {
1905     TextRun::setAllowsRoundingHacks(true);
1906 }
1907
1908 void Internals::insertAuthorCSS(const String& css, ExceptionCode& ec) const
1909 {
1910     Document* document = contextDocument();
1911     if (!document) {
1912         ec = INVALID_ACCESS_ERR;
1913         return;
1914     }
1915
1916     auto parsedSheet = StyleSheetContents::create(*document);
1917     parsedSheet.get().setIsUserStyleSheet(false);
1918     parsedSheet.get().parseString(css);
1919     document->styleSheetCollection().addAuthorSheet(WTF::move(parsedSheet));
1920 }
1921
1922 void Internals::insertUserCSS(const String& css, ExceptionCode& ec) const
1923 {
1924     Document* document = contextDocument();
1925     if (!document) {
1926         ec = INVALID_ACCESS_ERR;
1927         return;
1928     }
1929
1930     auto parsedSheet = StyleSheetContents::create(*document);
1931     parsedSheet.get().setIsUserStyleSheet(true);
1932     parsedSheet.get().parseString(css);
1933     document->styleSheetCollection().addUserSheet(WTF::move(parsedSheet));
1934 }
1935
1936 String Internals::counterValue(Element* element)
1937 {
1938     if (!element)
1939         return String();
1940
1941     return counterValueForElement(element);
1942 }
1943
1944 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1945 {
1946     if (!element)
1947         return 0;
1948
1949     return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1950 }
1951
1952 Vector<String> Internals::shortcutIconURLs() const
1953 {
1954     Vector<String> vector;
1955
1956     if (!frame())
1957         return vector;
1958
1959     auto string = frame()->loader().icon().url().string();
1960     if (!string.isNull())
1961         vector.append(string);
1962     return vector;
1963 }
1964
1965 int Internals::numberOfPages(float pageWidth, float pageHeight)
1966 {
1967     if (!frame())
1968         return -1;
1969
1970     return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
1971 }
1972
1973 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionCode& ec) const
1974 {
1975     if (!frame()) {
1976         ec = INVALID_ACCESS_ERR;
1977         return String();
1978     }
1979
1980     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
1981 }
1982
1983 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionCode& ec) const
1984 {
1985     if (!frame()) {
1986         ec = INVALID_ACCESS_ERR;
1987         return String();
1988     }
1989
1990     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
1991 }
1992
1993 void Internals::setPageScaleFactor(float scaleFactor, int x, int y, ExceptionCode& ec)
1994 {
1995     Document* document = contextDocument();
1996     if (!document || !document->page()) {
1997         ec = INVALID_ACCESS_ERR;
1998         return;
1999     }
2000     Page* page = document->page();
2001     page->setPageScaleFactor(scaleFactor, IntPoint(x, y));
2002 }
2003
2004 void Internals::setPageZoomFactor(float zoomFactor, ExceptionCode& ec)
2005 {
2006     Document* document = contextDocument();
2007     if (!document || !document->frame()) {
2008         ec = INVALID_ACCESS_ERR;
2009         return;
2010     }
2011     Frame* frame = document->frame();
2012     frame->setPageZoomFactor(zoomFactor);
2013 }
2014
2015 void Internals::setUseFixedLayout(bool useFixedLayout, ExceptionCode& ec)
2016 {
2017     Document* document = contextDocument();
2018     if (!document || !document->view()) {
2019         ec = INVALID_ACCESS_ERR;
2020         return;
2021     }
2022     FrameView* frameView = document->view();
2023     frameView->setUseFixedLayout(useFixedLayout);
2024 }
2025
2026 void Internals::setFixedLayoutSize(int width, int height, ExceptionCode& ec)
2027 {
2028     Document* document = contextDocument();
2029     if (!document || !document->view()) {
2030         ec = INVALID_ACCESS_ERR;
2031         return;
2032     }
2033     FrameView* frameView = document->view();
2034     frameView->setFixedLayoutSize(IntSize(width, height));
2035 }
2036
2037 void Internals::setHeaderHeight(float height)
2038 {
2039     Document* document = contextDocument();
2040     if (!document || !document->view())
2041         return;
2042
2043     FrameView* frameView = document->view();
2044     frameView->setHeaderHeight(height);
2045 }
2046
2047 void Internals::setFooterHeight(float height)
2048 {
2049     Document* document = contextDocument();
2050     if (!document || !document->view())
2051         return;
2052
2053     FrameView* frameView = document->view();
2054     frameView->setFooterHeight(height);
2055 }
2056     
2057 void Internals::setTopContentInset(float contentInset)
2058 {
2059     Document* document = contextDocument();
2060     if (!document)
2061         return;
2062     
2063     Page* page = document->page();
2064     page->setTopContentInset(contentInset);
2065 }
2066
2067 #if ENABLE(FULLSCREEN_API)
2068 void Internals::webkitWillEnterFullScreenForElement(Element* element)
2069 {
2070     Document* document = contextDocument();
2071     if (!document)
2072         return;
2073     document->webkitWillEnterFullScreenForElement(element);
2074 }
2075
2076 void Internals::webkitDidEnterFullScreenForElement(Element* element)
2077 {
2078     Document* document = contextDocument();
2079     if (!document)
2080         return;
2081     document->webkitDidEnterFullScreenForElement(element);
2082 }
2083
2084 void Internals::webkitWillExitFullScreenForElement(Element* element)
2085 {
2086     Document* document = contextDocument();
2087     if (!document)
2088         return;
2089     document->webkitWillExitFullScreenForElement(element);
2090 }
2091
2092 void Internals::webkitDidExitFullScreenForElement(Element* element)
2093 {
2094     Document* document = contextDocument();
2095     if (!document)
2096         return;
2097     document->webkitDidExitFullScreenForElement(element);
2098 }
2099 #endif
2100
2101 void Internals::setApplicationCacheOriginQuota(unsigned long long quota)
2102 {
2103     Document* document = contextDocument();
2104     if (!document)
2105         return;
2106     ApplicationCacheStorage::singleton().storeUpdatedQuotaForOrigin(document->securityOrigin(), quota);
2107 }
2108
2109 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
2110 {
2111     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2112 }
2113
2114 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
2115 {
2116     SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
2117 }
2118
2119 PassRefPtr<MallocStatistics> Internals::mallocStatistics() const
2120 {
2121     return MallocStatistics::create();
2122 }
2123
2124 PassRefPtr<TypeConversions> Internals::typeConversions() const
2125 {
2126     return TypeConversions::create();
2127 }
2128
2129 PassRefPtr<MemoryInfo> Internals::memoryInfo() const
2130 {
2131     return MemoryInfo::create();
2132 }
2133
2134 Vector<String> Internals::getReferencedFilePaths() const
2135 {
2136     frame()->loader().history().saveDocumentAndScrollState();
2137     return FormController::getReferencedFilePaths(frame()->loader().history().currentItem()->documentState());
2138 }
2139
2140 void Internals::startTrackingRepaints(ExceptionCode& ec)
2141 {
2142     Document* document = contextDocument();
2143     if (!document || !document->view()) {
2144         ec = INVALID_ACCESS_ERR;
2145         return;
2146     }
2147
2148     FrameView* frameView = document->view();
2149     frameView->setTracksRepaints(true);
2150 }
2151
2152 void Internals::stopTrackingRepaints(ExceptionCode& ec)
2153 {
2154     Document* document = contextDocument();
2155     if (!document || !document->view()) {
2156         ec = INVALID_ACCESS_ERR;
2157         return;
2158     }
2159
2160     FrameView* frameView = document->view();
2161     frameView->setTracksRepaints(false);
2162 }
2163
2164 void Internals::startTrackingLayerFlushes(ExceptionCode& ec)
2165 {
2166     Document* document = contextDocument();
2167     if (!document || !document->renderView()) {
2168         ec = INVALID_ACCESS_ERR;
2169         return;
2170     }
2171
2172     document->renderView()->compositor().startTrackingLayerFlushes();
2173 }
2174
2175 unsigned long Internals::layerFlushCount(ExceptionCode& ec)
2176 {
2177     Document* document = contextDocument();
2178     if (!document || !document->renderView()) {
2179         ec = INVALID_ACCESS_ERR;
2180         return 0;
2181     }
2182
2183     return document->renderView()->compositor().layerFlushCount();
2184 }
2185
2186 void Internals::startTrackingStyleRecalcs(ExceptionCode& ec)
2187 {
2188     Document* document = contextDocument();
2189     if (!document) {
2190         ec = INVALID_ACCESS_ERR;
2191         return;
2192     }
2193     document->startTrackingStyleRecalcs();
2194 }
2195
2196 unsigned long Internals::styleRecalcCount(ExceptionCode& ec)
2197 {
2198     Document* document = contextDocument();
2199     if (!document) {
2200         ec = INVALID_ACCESS_ERR;
2201         return 0;
2202     }
2203     
2204     return document->styleRecalcCount();
2205 }
2206
2207 void Internals::startTrackingCompositingUpdates(ExceptionCode& ec)
2208 {
2209     Document* document = contextDocument();
2210     if (!document || !document->renderView()) {
2211         ec = INVALID_ACCESS_ERR;
2212         return;
2213     }
2214
2215     document->renderView()->compositor().startTrackingCompositingUpdates();
2216 }
2217
2218 unsigned long Internals::compositingUpdateCount(ExceptionCode& ec)
2219 {
2220     Document* document = contextDocument();
2221     if (!document || !document->renderView()) {
2222         ec = INVALID_ACCESS_ERR;
2223         return 0;
2224     }
2225     
2226     return document->renderView()->compositor().compositingUpdateCount();
2227 }
2228
2229 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(ExceptionCode& ec)
2230 {
2231     updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(nullptr, ec);
2232 }
2233
2234 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionCode& ec)
2235 {
2236     Document* document;
2237     if (!node)
2238         document = contextDocument();
2239     else if (is<Document>(*node))
2240         document = downcast<Document>(node);
2241     else if (is<HTMLIFrameElement>(*node))
2242         document = downcast<HTMLIFrameElement>(*node).contentDocument();
2243     else {
2244         ec = TypeError;
2245         return;
2246     }
2247
2248     document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
2249 }
2250
2251 unsigned Internals::layoutCount() const
2252 {
2253     Document* document = contextDocument();
2254     if (!document || !document->view())
2255         return 0;
2256     return document->view()->layoutCount();
2257 }
2258
2259 #if !PLATFORM(IOS)
2260 static const char* cursorTypeToString(Cursor::Type cursorType)
2261 {
2262     switch (cursorType) {
2263     case Cursor::Pointer: return "Pointer";
2264     case Cursor::Cross: return "Cross";
2265     case Cursor::Hand: return "Hand";
2266     case Cursor::IBeam: return "IBeam";
2267     case Cursor::Wait: return "Wait";
2268     case Cursor::Help: return "Help";
2269     case Cursor::EastResize: return "EastResize";
2270     case Cursor::NorthResize: return "NorthResize";
2271     case Cursor::NorthEastResize: return "NorthEastResize";
2272     case Cursor::NorthWestResize: return "NorthWestResize";
2273     case Cursor::SouthResize: return "SouthResize";
2274     case Cursor::SouthEastResize: return "SouthEastResize";
2275     case Cursor::SouthWestResize: return "SouthWestResize";
2276     case Cursor::WestResize: return "WestResize";
2277     case Cursor::NorthSouthResize: return "NorthSouthResize";
2278     case Cursor::EastWestResize: return "EastWestResize";
2279     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
2280     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
2281     case Cursor::ColumnResize: return "ColumnResize";
2282     case Cursor::RowResize: return "RowResize";
2283     case Cursor::MiddlePanning: return "MiddlePanning";
2284     case Cursor::EastPanning: return "EastPanning";
2285     case Cursor::NorthPanning: return "NorthPanning";
2286     case Cursor::NorthEastPanning: return "NorthEastPanning";
2287     case Cursor::NorthWestPanning: return "NorthWestPanning";
2288     case Cursor::SouthPanning: return "SouthPanning";
2289     case Cursor::SouthEastPanning: return "SouthEastPanning";
2290     case Cursor::SouthWestPanning: return "SouthWestPanning";
2291     case Cursor::WestPanning: return "WestPanning";
2292     case Cursor::Move: return "Move";
2293     case Cursor::VerticalText: return "VerticalText";
2294     case Cursor::Cell: return "Cell";
2295     case Cursor::ContextMenu: return "ContextMenu";
2296     case Cursor::Alias: return "Alias";
2297     case Cursor::Progress: return "Progress";
2298     case Cursor::NoDrop: return "NoDrop";
2299     case Cursor::Copy: return "Copy";
2300     case Cursor::None: return "None";
2301     case Cursor::NotAllowed: return "NotAllowed";
2302     case Cursor::ZoomIn: return "ZoomIn";
2303     case Cursor::ZoomOut: return "ZoomOut";
2304     case Cursor::Grab: return "Grab";
2305     case Cursor::Grabbing: return "Grabbing";
2306     case Cursor::Custom: return "Custom";
2307     }
2308
2309     ASSERT_NOT_REACHED();
2310     return "UNKNOWN";
2311 }
2312 #endif
2313
2314 String Internals::getCurrentCursorInfo(ExceptionCode& ec)
2315 {
2316     Document* document = contextDocument();
2317     if (!document || !document->frame()) {
2318         ec = INVALID_ACCESS_ERR;
2319         return String();
2320     }
2321
2322 #if !PLATFORM(IOS)
2323     Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
2324
2325     StringBuilder result;
2326     result.appendLiteral("type=");
2327     result.append(cursorTypeToString(cursor.type()));
2328     result.appendLiteral(" hotSpot=");
2329     result.appendNumber(cursor.hotSpot().x());
2330     result.append(',');
2331     result.appendNumber(cursor.hotSpot().y());
2332     if (cursor.image()) {
2333         FloatSize size = cursor.image()->size();
2334         result.appendLiteral(" image=");
2335         result.appendNumber(size.width());
2336         result.append('x');
2337         result.appendNumber(size.height());
2338     }
2339 #if ENABLE(MOUSE_CURSOR_SCALE)
2340     if (cursor.imageScaleFactor() != 1) {
2341         result.appendLiteral(" scale=");
2342         NumberToStringBuffer buffer;
2343         result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
2344     }
2345 #endif
2346     return result.toString();
2347 #else
2348     return "FAIL: Cursor details not available on this platform.";
2349 #endif
2350 }
2351
2352 PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
2353 {
2354     Vector<uint8_t> bytes = value->data();
2355     return ArrayBuffer::create(bytes.data(), bytes.size());
2356 }
2357
2358 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
2359 {
2360     Vector<uint8_t> bytes;
2361     bytes.append(static_cast<const uint8_t*>(buffer->data()), buffer->byteLength());
2362     return SerializedScriptValue::adopt(bytes);
2363 }
2364
2365 bool Internals::isFromCurrentWorld(Deprecated::ScriptValue value) const
2366 {
2367     ASSERT(!value.hasNoValue());
2368     
2369     JSC::ExecState* exec = contextDocument()->vm().topCallFrame;
2370     if (!value.isObject() || &worldForDOMObject(value.jsValue().getObject()) == &currentWorld(exec))
2371         return true;
2372     return false;
2373 }
2374
2375 void Internals::setUsesOverlayScrollbars(bool enabled)
2376 {
2377     WebCore::Settings::setUsesOverlayScrollbars(enabled);
2378 }
2379
2380 void Internals::forceReload(bool endToEnd)
2381 {
2382     frame()->loader().reload(endToEnd);
2383 }
2384
2385 #if ENABLE(ENCRYPTED_MEDIA_V2)
2386 void Internals::initializeMockCDM()
2387 {
2388     CDM::registerCDMFactory([](CDM* cdm) { return std::make_unique<MockCDM>(cdm); },
2389         MockCDM::supportsKeySystem, MockCDM::supportsKeySystemAndMimeType);
2390 }
2391 #endif
2392
2393 String Internals::markerTextForListItem(Element* element, ExceptionCode& ec)
2394 {
2395     if (!element) {
2396         ec = INVALID_ACCESS_ERR;
2397         return String();
2398     }
2399     return WebCore::markerTextForListItem(element);
2400 }
2401
2402 String Internals::toolTipFromElement(Element* element, ExceptionCode& ec) const
2403 {
2404     if (!element) {
2405         ec = INVALID_ACCESS_ERR;
2406         return String();
2407     }
2408     HitTestResult result;
2409     result.setInnerNode(element);
2410     TextDirection dir;
2411     return result.title(dir);
2412 }
2413
2414 String Internals::getImageSourceURL(Element* element, ExceptionCode& ec)
2415 {
2416     if (!element) {
2417         ec = INVALID_ACCESS_ERR;
2418         return String();
2419     }
2420     return element->imageSourceURL();
2421 }
2422
2423 #if ENABLE(VIDEO)
2424 void Internals::simulateAudioInterruption(Node* node)
2425 {
2426 #if USE(GSTREAMER)
2427     HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2428     element->player()->simulateAudioInterruption();
2429 #else
2430     UNUSED_PARAM(node);
2431 #endif
2432 }
2433
2434 bool Internals::mediaElementHasCharacteristic(Node* node, const String& characteristic, ExceptionCode& ec)
2435 {
2436     if (!is<HTMLMediaElement>(*node))
2437         return false;
2438
2439     HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2440
2441     if (equalIgnoringCase(characteristic, "Audible"))
2442         return element->hasAudio();
2443     if (equalIgnoringCase(characteristic, "Visual"))
2444         return element->hasVideo();
2445     if (equalIgnoringCase(characteristic, "Legible"))
2446         return element->hasClosedCaptions();
2447
2448     ec = SYNTAX_ERR;
2449     return false;
2450 }
2451 #endif
2452
2453 bool Internals::isSelectPopupVisible(Node* node)
2454 {
2455     if (!is<HTMLSelectElement>(*node))
2456         return false;
2457
2458     HTMLSelectElement& select = downcast<HTMLSelectElement>(*node);
2459
2460     auto* renderer = select.renderer();
2461     ASSERT(renderer);
2462     if (!is<RenderMenuList>(*renderer))
2463         return false;
2464
2465 #if !PLATFORM(IOS)
2466     return downcast<RenderMenuList>(*renderer).popupIsVisible();
2467 #else
2468     return false;
2469 #endif // !PLATFORM(IOS)
2470 }
2471
2472 String Internals::captionsStyleSheetOverride(ExceptionCode& ec)
2473 {
2474     Document* document = contextDocument();
2475     if (!document || !document->page()) {
2476         ec = INVALID_ACCESS_ERR;
2477         return emptyString();
2478     }
2479
2480 #if ENABLE(VIDEO_TRACK)
2481     return document->page()->group().captionPreferences()->captionsStyleSheetOverride();
2482 #else
2483     return emptyString();
2484 #endif
2485 }
2486
2487 void Internals::setCaptionsStyleSheetOverride(const String& override, ExceptionCode& ec)
2488 {
2489     Document* document = contextDocument();
2490     if (!document || !document->page()) {
2491         ec = INVALID_ACCESS_ERR;
2492         return;
2493     }
2494
2495 #if ENABLE(VIDEO_TRACK)
2496     document->page()->group().captionPreferences()->setCaptionsStyleSheetOverride(override);
2497 #else
2498     UNUSED_PARAM(override);
2499 #endif
2500 }
2501
2502 void Internals::setPrimaryAudioTrackLanguageOverride(const String& language, ExceptionCode& ec)
2503 {
2504     Document* document = contextDocument();
2505     if (!document || !document->page()) {
2506         ec = INVALID_ACCESS_ERR;
2507         return;
2508     }
2509
2510 #if ENABLE(VIDEO_TRACK)
2511     document->page()->group().captionPreferences()->setPrimaryAudioTrackLanguageOverride(language);
2512 #else
2513     UNUSED_PARAM(language);
2514 #endif
2515 }
2516
2517 void Internals::setCaptionDisplayMode(const String& mode, ExceptionCode& ec)
2518 {
2519     Document* document = contextDocument();
2520     if (!document || !document->page()) {
2521         ec = INVALID_ACCESS_ERR;
2522         return;
2523     }
2524     
2525 #if ENABLE(VIDEO_TRACK)
2526     CaptionUserPreferences* captionPreferences = document->page()->group().captionPreferences();
2527     
2528     if (equalIgnoringCase(mode, "Automatic"))
2529         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::Automatic);
2530     else if (equalIgnoringCase(mode, "ForcedOnly"))
2531         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
2532     else if (equalIgnoringCase(mode, "AlwaysOn"))
2533         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn);
2534     else
2535         ec = SYNTAX_ERR;
2536 #else
2537     UNUSED_PARAM(mode);
2538 #endif
2539 }
2540
2541 #if ENABLE(VIDEO)
2542 PassRefPtr<TimeRanges> Internals::createTimeRanges(Float32Array* startTimes, Float32Array* endTimes)
2543 {
2544     ASSERT(startTimes && endTimes);
2545     ASSERT(startTimes->length() == endTimes->length());
2546     RefPtr<TimeRanges> ranges = TimeRanges::create();
2547
2548     unsigned count = std::min(startTimes->length(), endTimes->length());
2549     for (unsigned i = 0; i < count; ++i)
2550         ranges->add(startTimes->item(i), endTimes->item(i));
2551     return ranges;
2552 }
2553
2554 double Internals::closestTimeToTimeRanges(double time, TimeRanges* ranges)
2555 {
2556     return ranges->nearest(time);
2557 }
2558 #endif
2559
2560 Ref<ClientRect> Internals::selectionBounds(ExceptionCode& ec)
2561 {
2562     Document* document = contextDocument();
2563     if (!document || !document->frame()) {
2564         ec = INVALID_ACCESS_ERR;
2565         return ClientRect::create();
2566     }
2567
2568     return ClientRect::create(document->frame()->selection().selectionBounds());
2569 }
2570
2571 #if ENABLE(VIBRATION)
2572 bool Internals::isVibrating()
2573 {
2574     Page* page = contextDocument()->page();
2575     ASSERT(page);
2576
2577     return Vibration::from(page)->isVibrating();
2578 }
2579 #endif
2580
2581 bool Internals::isPluginUnavailabilityIndicatorObscured(Element* element, ExceptionCode& ec)
2582 {
2583     if (!element) {
2584         ec = INVALID_ACCESS_ERR;
2585         return false;
2586     }
2587
2588     auto* renderer = element->renderer();
2589     if (!is<RenderEmbeddedObject>(renderer)) {
2590         ec = INVALID_ACCESS_ERR;
2591         return false;
2592     }
2593
2594     return downcast<RenderEmbeddedObject>(*renderer).isReplacementObscured();
2595 }
2596     
2597 bool Internals::isPluginSnapshotted(Element* element, ExceptionCode& ec)
2598 {
2599     if (!element) {
2600         ec = INVALID_ACCESS_ERR;
2601         return false;
2602     }
2603     HTMLPlugInElement* pluginElement = downcast<HTMLPlugInElement>(element);
2604     return pluginElement->displayState() <= HTMLPlugInElement::DisplayingSnapshot;
2605 }
2606     
2607 #if ENABLE(MEDIA_SOURCE)
2608 void Internals::initializeMockMediaSource()
2609 {
2610 #if USE(AVFOUNDATION)
2611     WebCore::Settings::setAVFoundationEnabled(false);
2612 #endif
2613     MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
2614 }
2615
2616 Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer* buffer, const AtomicString& trackID)
2617 {
2618     if (!buffer)
2619         return Vector<String>();
2620
2621     return buffer->bufferedSamplesForTrackID(trackID);
2622 }
2623 #endif
2624
2625 #if ENABLE(VIDEO)
2626 void Internals::beginMediaSessionInterruption()
2627 {
2628     PlatformMediaSessionManager::sharedManager().beginInterruption(PlatformMediaSession::SystemInterruption);
2629 }
2630
2631 void Internals::endMediaSessionInterruption(const String& flagsString)
2632 {
2633     PlatformMediaSession::EndInterruptionFlags flags = PlatformMediaSession::NoFlags;
2634
2635     if (equalIgnoringCase(flagsString, "MayResumePlaying"))
2636         flags = PlatformMediaSession::MayResumePlaying;
2637     
2638     PlatformMediaSessionManager::sharedManager().endInterruption(flags);
2639 }
2640
2641 void Internals::applicationWillEnterForeground() const
2642 {
2643     PlatformMediaSessionManager::sharedManager().applicationWillEnterForeground();
2644 }
2645
2646 void Internals::applicationWillEnterBackground() const
2647 {
2648     PlatformMediaSessionManager::sharedManager().applicationWillEnterBackground();
2649 }
2650
2651 void Internals::setMediaSessionRestrictions(const String& mediaTypeString, const String& restrictionsString, ExceptionCode& ec)
2652 {
2653     PlatformMediaSession::MediaType mediaType = PlatformMediaSession::None;
2654     if (equalIgnoringCase(mediaTypeString, "Video"))
2655         mediaType = PlatformMediaSession::Video;
2656     else if (equalIgnoringCase(mediaTypeString, "Audio"))
2657         mediaType = PlatformMediaSession::Audio;
2658     else if (equalIgnoringCase(mediaTypeString, "WebAudio"))
2659         mediaType = PlatformMediaSession::WebAudio;
2660     else {
2661         ec = INVALID_ACCESS_ERR;
2662         return;
2663     }
2664
2665     PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
2666     PlatformMediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions);
2667
2668     restrictions = PlatformMediaSessionManager::NoRestrictions;
2669
2670     Vector<String> restrictionsArray;
2671     restrictionsString.split(',', false, restrictionsArray);
2672     for (auto& restrictionString : restrictionsArray) {
2673         if (equalIgnoringCase(restrictionString, "ConcurrentPlaybackNotPermitted"))
2674             restrictions |= PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted;
2675         if (equalIgnoringCase(restrictionString, "InlineVideoPlaybackRestricted"))
2676             restrictions |= PlatformMediaSessionManager::InlineVideoPlaybackRestricted;
2677         if (equalIgnoringCase(restrictionString, "MetadataPreloadingNotPermitted"))
2678             restrictions |= PlatformMediaSessionManager::MetadataPreloadingNotPermitted;
2679         if (equalIgnoringCase(restrictionString, "AutoPreloadingNotPermitted"))
2680             restrictions |= PlatformMediaSessionManager::AutoPreloadingNotPermitted;
2681         if (equalIgnoringCase(restrictionString, "BackgroundProcessPlaybackRestricted"))
2682             restrictions |= PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted;
2683         if (equalIgnoringCase(restrictionString, "BackgroundTabPlaybackRestricted"))
2684             restrictions |= PlatformMediaSessionManager::BackgroundTabPlaybackRestricted;
2685         if (equalIgnoringCase(restrictionString, "InterruptedPlaybackNotPermitted"))
2686             restrictions |= PlatformMediaSessionManager::InterruptedPlaybackNotPermitted;
2687     }
2688     PlatformMediaSessionManager::sharedManager().addRestriction(mediaType, restrictions);
2689 }
2690
2691 void Internals::setMediaElementRestrictions(HTMLMediaElement* element, const String& restrictionsString, ExceptionCode& ec)
2692 {
2693     if (!element) {
2694         ec = INVALID_ACCESS_ERR;
2695         return;
2696     }
2697
2698     MediaElementSession::BehaviorRestrictions restrictions = element->mediaSession().behaviorRestrictions();
2699     element->mediaSession().removeBehaviorRestriction(restrictions);
2700
2701     restrictions = MediaElementSession::NoRestrictions;
2702
2703     Vector<String> restrictionsArray;
2704     restrictionsString.split(',', false, restrictionsArray);
2705     for (auto& restrictionString : restrictionsArray) {
2706         if (equalIgnoringCase(restrictionString, "NoRestrictions"))
2707             restrictions |= MediaElementSession::NoRestrictions;
2708         if (equalIgnoringCase(restrictionString, "RequireUserGestureForLoad"))
2709             restrictions |= MediaElementSession::RequireUserGestureForLoad;
2710         if (equalIgnoringCase(restrictionString, "RequireUserGestureForRateChange"))
2711             restrictions |= MediaElementSession::RequireUserGestureForRateChange;
2712         if (equalIgnoringCase(restrictionString, "RequireUserGestureForFullscreen"))
2713             restrictions |= MediaElementSession::RequireUserGestureForFullscreen;
2714         if (equalIgnoringCase(restrictionString, "RequirePageConsentToLoadMedia"))
2715             restrictions |= MediaElementSession::RequirePageConsentToLoadMedia;
2716         if (equalIgnoringCase(restrictionString, "RequirePageConsentToResumeMedia"))
2717             restrictions |= MediaElementSession::RequirePageConsentToResumeMedia;
2718 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
2719         if (equalIgnoringCase(restrictionString, "RequireUserGestureToShowPlaybackTargetPicker"))
2720             restrictions |= MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker;
2721         if (equalIgnoringCase(restrictionString, "WirelessVideoPlaybackDisabled"))
2722             restrictions |= MediaElementSession::WirelessVideoPlaybackDisabled;
2723 #endif
2724         if (equalIgnoringCase(restrictionString, "RequireUserGestureForAudioRateChange"))
2725             restrictions |= MediaElementSession::RequireUserGestureForAudioRateChange;
2726     }
2727     element->mediaSession().addBehaviorRestriction(restrictions);
2728 }
2729
2730 void Internals::postRemoteControlCommand(const String& commandString, ExceptionCode& ec)
2731 {
2732     PlatformMediaSession::RemoteControlCommandType command;
2733     
2734     if (equalIgnoringCase(commandString, "Play"))
2735         command = PlatformMediaSession::PlayCommand;
2736     else if (equalIgnoringCase(commandString, "Pause"))
2737         command = PlatformMediaSession::PauseCommand;
2738     else if (equalIgnoringCase(commandString, "Stop"))
2739         command = PlatformMediaSession::StopCommand;
2740     else if (equalIgnoringCase(commandString, "TogglePlayPause"))
2741         command = PlatformMediaSession::TogglePlayPauseCommand;
2742     else if (equalIgnoringCase(commandString, "BeginSeekingBackward"))
2743         command = PlatformMediaSession::BeginSeekingBackwardCommand;
2744     else if (equalIgnoringCase(commandString, "EndSeekingBackward"))
2745         command = PlatformMediaSession::EndSeekingBackwardCommand;
2746     else if (equalIgnoringCase(commandString, "BeginSeekingForward"))
2747         command = PlatformMediaSession::BeginSeekingForwardCommand;
2748     else if (equalIgnoringCase(commandString, "EndSeekingForward"))
2749         command = PlatformMediaSession::EndSeekingForwardCommand;
2750     else {
2751         ec = INVALID_ACCESS_ERR;
2752         return;
2753     }
2754     
2755     PlatformMediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command);
2756 }
2757
2758 bool Internals::elementIsBlockingDisplaySleep(Element* element) const
2759 {
2760     HTMLMediaElement* mediaElement = downcast<HTMLMediaElement>(element);
2761     return mediaElement ? mediaElement->isDisablingSleep() : false;
2762 }
2763
2764 #endif // ENABLE(VIDEO)
2765
2766 #if ENABLE(MEDIA_SESSION)
2767 static MediaSessionInterruptingCategory interruptingCategoryFromString(const String& interruptingCategoryString)
2768 {
2769     if (interruptingCategoryString == "content")
2770         return MediaSessionInterruptingCategory::Content;
2771     if (interruptingCategoryString == "transient")
2772         return MediaSessionInterruptingCategory::Transient;
2773     if (interruptingCategoryString == "transient-solo")
2774         return MediaSessionInterruptingCategory::TransientSolo;
2775     ASSERT_NOT_REACHED();
2776 }
2777
2778 void Internals::sendMediaSessionStartOfInterruptionNotification(const String& interruptingCategoryString)
2779 {
2780     MediaSessionManager::singleton().didReceiveStartOfInterruptionNotification(interruptingCategoryFromString(interruptingCategoryString));
2781 }
2782
2783 void Internals::sendMediaSessionEndOfInterruptionNotification(const String& interruptingCategoryString)
2784 {
2785     MediaSessionManager::singleton().didReceiveEndOfInterruptionNotification(interruptingCategoryFromString(interruptingCategoryString));
2786 }
2787
2788 String Internals::mediaSessionCurrentState(MediaSession* session) const
2789 {
2790     switch (session->currentState()) {
2791     case MediaSession::State::Active:
2792         return "active";
2793     case MediaSession::State::Interrupted:
2794         return "interrupted";
2795     case MediaSession::State::Idle:
2796         return "idle";
2797     }
2798 }
2799 #endif // ENABLE(MEDIA_SESSION)
2800
2801 #if ENABLE(WEB_AUDIO)
2802 void Internals::setAudioContextRestrictions(AudioContext* context, const String &restrictionsString, ExceptionCode &ec)
2803 {
2804     if (!context) {
2805         ec = INVALID_ACCESS_ERR;
2806         return;
2807     }
2808
2809     AudioContext::BehaviorRestrictions restrictions = context->behaviorRestrictions();
2810     context->removeBehaviorRestriction(restrictions);
2811
2812     restrictions = MediaElementSession::NoRestrictions;
2813
2814     Vector<String> restrictionsArray;
2815     restrictionsString.split(',', false, restrictionsArray);
2816     for (auto& restrictionString : restrictionsArray) {
2817         if (equalIgnoringCase(restrictionString, "NoRestrictions"))
2818             restrictions |= AudioContext::NoRestrictions;
2819         if (equalIgnoringCase(restrictionString, "RequireUserGestureForAudioStart"))
2820             restrictions |= AudioContext::RequireUserGestureForAudioStartRestriction;
2821         if (equalIgnoringCase(restrictionString, "RequirePageConsentForAudioStart"))
2822             restrictions |= AudioContext::RequirePageConsentForAudioStartRestriction;
2823     }
2824     context->addBehaviorRestriction(restrictions);
2825 }
2826 #endif
2827
2828 void Internals::simulateSystemSleep() const
2829 {
2830 #if ENABLE(VIDEO)
2831     PlatformMediaSessionManager::sharedManager().systemWillSleep();
2832 #endif
2833 }
2834
2835 void Internals::simulateSystemWake() const
2836 {
2837 #if ENABLE(VIDEO)
2838     PlatformMediaSessionManager::sharedManager().systemDidWake();
2839 #endif
2840 }
2841
2842
2843 void Internals::installMockPageOverlay(const String& overlayType, ExceptionCode& ec)
2844 {
2845     Document* document = contextDocument();
2846     if (!document || !document->frame()) {
2847         ec = INVALID_ACCESS_ERR;
2848         return;
2849     }
2850
2851     MockPageOverlayClient::singleton().installOverlay(document->frame()->mainFrame(), overlayType == "view" ? PageOverlay::OverlayType::View : PageOverlay::OverlayType::Document);
2852 }
2853
2854 String Internals::pageOverlayLayerTreeAsText(ExceptionCode& ec) const
2855 {
2856     Document* document = contextDocument();
2857     if (!document || !document->frame()) {
2858         ec = INVALID_ACCESS_ERR;
2859         return String();
2860     }
2861
2862     document->updateLayout();
2863
2864     return MockPageOverlayClient::singleton().layerTreeAsText(document->frame()->mainFrame());
2865 }
2866
2867 void Internals::setPageMuted(bool muted)
2868 {
2869     Document* document = contextDocument();
2870     if (!document)
2871         return;
2872
2873     if (Page* page = document->page())
2874         page->setMuted(muted);
2875 }
2876
2877 bool Internals::isPagePlayingAudio()
2878 {
2879     Document* document = contextDocument();
2880     if (!document || !document->page())
2881         return false;
2882
2883     return !!(document->page()->mediaState() & MediaProducer::IsPlayingAudio);
2884 }
2885
2886 RefPtr<File> Internals::createFile(const String& path)
2887 {
2888     Document* document = contextDocument();
2889     if (!document)
2890         return nullptr;
2891
2892     URL url = document->completeURL(path);
2893     if (!url.isLocalFile())
2894         return nullptr;
2895
2896     return File::create(url.fileSystemPath());
2897 }
2898
2899 void Internals::queueMicroTask(int testNumber)
2900 {
2901     if (contextDocument())
2902         MicroTaskQueue::singleton().queueMicroTask(std::make_unique<MicroTaskTest>(contextDocument()->createWeakPtr(), testNumber));
2903 }
2904
2905 #if ENABLE(CONTENT_FILTERING)
2906 MockContentFilterSettings& Internals::mockContentFilterSettings()
2907 {
2908     return MockContentFilterSettings::singleton();
2909 }
2910 #endif
2911
2912 #if ENABLE(CSS_SCROLL_SNAP)
2913 static void appendOffsets(StringBuilder& builder, const Vector<LayoutUnit>& snapOffsets)
2914 {
2915     bool justStarting = true;
2916
2917     builder.append("{ ");
2918     for (auto& coordinate : snapOffsets) {
2919         if (!justStarting)
2920             builder.append(", ");
2921         else
2922             justStarting = false;
2923         
2924         builder.append(String::number(coordinate.toUnsigned()));
2925     }
2926     builder.append(" }");
2927 }
2928     
2929 String Internals::scrollSnapOffsets(Element* element, ExceptionCode& ec)
2930 {
2931     if (!element) {
2932         ec = INVALID_ACCESS_ERR;
2933         return String();
2934     }
2935
2936     if (!element->renderBox())
2937         return String();
2938
2939     RenderBox& box = *element->renderBox();
2940     ScrollableArea* scrollableArea;
2941     
2942     if (box.isBody()) {
2943         FrameView* frameView = box.frame().mainFrame().view();
2944         if (!frameView || !frameView->isScrollable()) {
2945             ec = INVALID_ACCESS_ERR;
2946             return String();
2947         }
2948         scrollableArea = frameView;
2949         
2950     } else {
2951         if (!box.canBeScrolledAndHasScrollableArea()) {
2952             ec = INVALID_ACCESS_ERR;
2953             return String();
2954         }
2955         scrollableArea = box.layer();
2956     }
2957
2958     if (!scrollableArea)
2959         return String();
2960     
2961     StringBuilder result;
2962
2963     if (scrollableArea->horizontalSnapOffsets()) {
2964         result.append("horizontal = ");
2965         appendOffsets(result, *scrollableArea->horizontalSnapOffsets());
2966     }
2967
2968     if (scrollableArea->verticalSnapOffsets()) {
2969         if (result.length())
2970             result.append(", ");
2971
2972         result.append("vertical = ");
2973         appendOffsets(result, *scrollableArea->verticalSnapOffsets());
2974     }
2975
2976     return result.toString();
2977 }
2978 #endif
2979
2980 bool Internals::testPreloaderSettingViewport()
2981 {
2982     return testPreloadScannerViewportSupport(contextDocument());
2983 }
2984
2985 String Internals::pathStringWithShrinkWrappedRects(Vector<double> rectComponents, double radius, ExceptionCode& ec)
2986 {
2987     if (rectComponents.size() % 4) {
2988         ec = INVALID_ACCESS_ERR;
2989         return String();
2990     }
2991
2992     Vector<FloatRect> rects;
2993     while (!rectComponents.isEmpty()) {
2994         double height = rectComponents.takeLast();
2995         double width = rectComponents.takeLast();
2996         double y = rectComponents.takeLast();
2997         double x = rectComponents.takeLast();
2998
2999         rects.append(FloatRect(x, y, width, height));
3000     }
3001
3002     rects.reverse();
3003
3004     Path path = PathUtilities::pathWithShrinkWrappedRects(rects, radius);
3005
3006     String pathString;
3007     buildStringFromPath(path, pathString);
3008
3009     return pathString;
3010 }
3011
3012 }