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