31bf51743a881cfcb825a578b46ab2cc2ccf5557
[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 DictionaryLookup::rangeAtHitTestResult(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->ownerScriptExecutable();
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 if (executable->isModuleProgramExecutable())
1489         result.appendLiteral("module");
1490     else if (executable->isProgramExecutable())
1491         result.appendLiteral("program");
1492 #if ENABLE(WEBASSEMBLY)
1493     else if (executable->isWebAssemblyExecutable())
1494         result.appendLiteral("WebAssembly");
1495 #endif
1496     else
1497         ASSERT_NOT_REACHED();
1498
1499     result.appendLiteral(" { ");
1500     result.appendNumber(startLine);
1501     result.append(':');
1502     result.appendNumber(startColumn);
1503     result.appendLiteral(" - ");
1504     result.appendNumber(endLine);
1505     result.append(':');
1506     result.appendNumber(endColumn);
1507     result.appendLiteral(" }");
1508
1509     return result.toString();
1510 }
1511
1512 void Internals::setBatteryStatus(const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
1513 {
1514     Document* document = contextDocument();
1515     if (!document || !document->page()) {
1516         ec = INVALID_ACCESS_ERR;
1517         return;
1518     }
1519
1520 #if ENABLE(BATTERY_STATUS)
1521     BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
1522 #else
1523     UNUSED_PARAM(eventType);
1524     UNUSED_PARAM(charging);
1525     UNUSED_PARAM(chargingTime);
1526     UNUSED_PARAM(dischargingTime);
1527     UNUSED_PARAM(level);
1528 #endif
1529 }
1530
1531 void Internals::setDeviceProximity(const String& eventType, double value, double min, double max, ExceptionCode& ec)
1532 {
1533     Document* document = contextDocument();
1534     if (!document || !document->page()) {
1535         ec = INVALID_ACCESS_ERR;
1536         return;
1537     }
1538
1539 #if ENABLE(PROXIMITY_EVENTS)
1540     DeviceProximityController::from(document->page())->didChangeDeviceProximity(value, min, max);
1541 #else
1542     UNUSED_PARAM(eventType);
1543     UNUSED_PARAM(value);
1544     UNUSED_PARAM(min);
1545     UNUSED_PARAM(max);
1546 #endif
1547 }
1548
1549 void Internals::updateEditorUINowIfScheduled()
1550 {
1551     if (Document* document = contextDocument()) {
1552         if (Frame* frame = document->frame())
1553             frame->editor().updateEditorUINowIfScheduled();
1554     }
1555 }
1556
1557 bool Internals::hasSpellingMarker(int from, int length, ExceptionCode&)
1558 {
1559     Document* document = contextDocument();
1560     if (!document || !document->frame())
1561         return false;
1562
1563     updateEditorUINowIfScheduled();
1564
1565     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1566 }
1567     
1568 bool Internals::hasAutocorrectedMarker(int from, int length, ExceptionCode&)
1569 {
1570     Document* document = contextDocument();
1571     if (!document || !document->frame())
1572         return false;
1573
1574     updateEditorUINowIfScheduled();
1575
1576     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
1577 }
1578
1579 void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionCode&)
1580 {
1581     if (!contextDocument() || !contextDocument()->frame())
1582         return;
1583
1584     if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
1585         contextDocument()->frame()->editor().toggleContinuousSpellChecking();
1586 }
1587
1588 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled, ExceptionCode&)
1589 {
1590     if (!contextDocument() || !contextDocument()->frame())
1591         return;
1592
1593 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1594     if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
1595         contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
1596 #else
1597     UNUSED_PARAM(enabled);
1598 #endif
1599 }
1600
1601 void Internals::setAutomaticLinkDetectionEnabled(bool enabled, ExceptionCode&)
1602 {
1603     if (!contextDocument() || !contextDocument()->frame())
1604         return;
1605
1606 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1607     if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
1608         contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
1609 #else
1610     UNUSED_PARAM(enabled);
1611 #endif
1612 }
1613
1614 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled, ExceptionCode&)
1615 {
1616     if (!contextDocument() || !contextDocument()->frame())
1617         return;
1618
1619 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1620     if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
1621         contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
1622 #else
1623     UNUSED_PARAM(enabled);
1624 #endif
1625 }
1626
1627 void Internals::setAutomaticTextReplacementEnabled(bool enabled, ExceptionCode&)
1628 {
1629     if (!contextDocument() || !contextDocument()->frame())
1630         return;
1631
1632 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1633     if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
1634         contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
1635 #else
1636     UNUSED_PARAM(enabled);
1637 #endif
1638 }
1639
1640 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled, ExceptionCode&)
1641 {
1642     if (!contextDocument() || !contextDocument()->frame())
1643         return;
1644
1645 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1646     if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
1647         contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
1648 #else
1649     UNUSED_PARAM(enabled);
1650 #endif
1651 }
1652
1653 bool Internals::isOverwriteModeEnabled(ExceptionCode&)
1654 {
1655     Document* document = contextDocument();
1656     if (!document || !document->frame())
1657         return false;
1658
1659     return document->frame()->editor().isOverwriteModeEnabled();
1660 }
1661
1662 void Internals::toggleOverwriteModeEnabled(ExceptionCode&)
1663 {
1664     Document* document = contextDocument();
1665     if (!document || !document->frame())
1666         return;
1667
1668     document->frame()->editor().toggleOverwriteModeEnabled();
1669 }
1670
1671 unsigned Internals::countMatchesForText(const String& text, unsigned findOptions, const String& markMatches, ExceptionCode&)
1672 {
1673     Document* document = contextDocument();
1674     if (!document || !document->frame())
1675         return 0;
1676
1677     bool mark = markMatches == "mark";
1678     return document->frame()->editor().countMatchesForText(text, nullptr, findOptions, 1000, mark, nullptr);
1679 }
1680
1681 const ProfilesArray& Internals::consoleProfiles() const
1682 {
1683     return contextDocument()->page()->console().profiles();
1684 }
1685
1686 unsigned Internals::numberOfLiveNodes() const
1687 {
1688     unsigned nodeCount = 0;
1689     for (auto* document : Document::allDocuments())
1690         nodeCount += document->referencingNodeCount();
1691     return nodeCount;
1692 }
1693
1694 unsigned Internals::numberOfLiveDocuments() const
1695 {
1696     return Document::allDocuments().size();
1697 }
1698
1699 Vector<String> Internals::consoleMessageArgumentCounts() const
1700 {
1701     Document* document = contextDocument();
1702     if (!document || !document->page())
1703         return Vector<String>();
1704
1705     InstrumentingAgents* instrumentingAgents = InspectorInstrumentation::instrumentingAgentsForPage(document->page());
1706     if (!instrumentingAgents)
1707         return Vector<String>();
1708
1709     InspectorConsoleAgent* consoleAgent = instrumentingAgents->webConsoleAgent();
1710     if (!consoleAgent)
1711         return Vector<String>();
1712
1713     Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
1714     Vector<String> result(counts.size());
1715     for (size_t i = 0; i < counts.size(); i++)
1716         result[i] = String::number(counts[i]);
1717     return result;
1718 }
1719
1720 PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
1721 {
1722     Page* page = contextDocument()->frame()->page();
1723     ASSERT(page);
1724
1725     DOMWindow* window = page->mainFrame().document()->domWindow();
1726     ASSERT(window);
1727
1728     m_frontendWindow = window->open(url, "", "", *window, *window);
1729     ASSERT(m_frontendWindow);
1730
1731     Page* frontendPage = m_frontendWindow->document()->page();
1732     ASSERT(frontendPage);
1733
1734     m_frontendClient = std::make_unique<InspectorFrontendClientDummy>(&page->inspectorController(), frontendPage);
1735     frontendPage->inspectorController().setInspectorFrontendClient(m_frontendClient.get());
1736
1737     bool isAutomaticInspection = false;
1738     m_frontendChannel = std::make_unique<InspectorFrontendChannelDummy>(frontendPage);
1739     page->inspectorController().connectFrontend(m_frontendChannel.get(), isAutomaticInspection);
1740
1741     return m_frontendWindow;
1742 }
1743
1744 void Internals::closeDummyInspectorFrontend()
1745 {
1746     Page* page = contextDocument()->frame()->page();
1747     ASSERT(page);
1748     ASSERT(m_frontendWindow);
1749
1750     page->inspectorController().disconnectFrontend(Inspector::DisconnectReason::InspectorDestroyed);
1751
1752     m_frontendClient = nullptr;
1753     m_frontendChannel = nullptr;
1754
1755     m_frontendWindow->close(m_frontendWindow->scriptExecutionContext());
1756     m_frontendWindow = nullptr;
1757 }
1758
1759 void Internals::setJavaScriptProfilingEnabled(bool enabled, ExceptionCode& ec)
1760 {
1761     Page* page = contextDocument()->frame()->page();
1762     if (!page) {
1763         ec = INVALID_ACCESS_ERR;
1764         return;
1765     }
1766
1767     page->inspectorController().setProfilerEnabled(enabled);
1768 }
1769
1770 void Internals::setInspectorIsUnderTest(bool isUnderTest, ExceptionCode& ec)
1771 {
1772     Page* page = contextDocument()->frame()->page();
1773     if (!page) {
1774         ec = INVALID_ACCESS_ERR;
1775         return;
1776     }
1777
1778     page->inspectorController().setIsUnderTest(isUnderTest);
1779 }
1780
1781 bool Internals::hasGrammarMarker(int from, int length, ExceptionCode&)
1782 {
1783     Document* document = contextDocument();
1784     if (!document || !document->frame())
1785         return false;
1786
1787     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1788 }
1789
1790 unsigned Internals::numberOfScrollableAreas(ExceptionCode&)
1791 {
1792     Document* document = contextDocument();
1793     if (!document || !document->frame())
1794         return 0;
1795
1796     unsigned count = 0;
1797     Frame* frame = document->frame();
1798     if (frame->view()->scrollableAreas())
1799         count += frame->view()->scrollableAreas()->size();
1800
1801     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1802         if (child->view() && child->view()->scrollableAreas())
1803             count += child->view()->scrollableAreas()->size();
1804     }
1805
1806     return count;
1807 }
1808     
1809 bool Internals::isPageBoxVisible(int pageNumber, ExceptionCode& ec)
1810 {
1811     Document* document = contextDocument();
1812     if (!document) {
1813         ec = INVALID_ACCESS_ERR;
1814         return false;
1815     }
1816
1817     return document->isPageBoxVisible(pageNumber);
1818 }
1819
1820 // FIXME: Remove the document argument. It is almost always the same as
1821 // contextDocument(), with the exception of a few tests that pass a
1822 // different document, and could just make the call through another Internals
1823 // instance instead.
1824 String Internals::layerTreeAsText(Document* document, ExceptionCode& ec) const
1825 {
1826     return layerTreeAsText(document, 0, ec);
1827 }
1828
1829 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionCode& ec) const
1830 {
1831     if (!document || !document->frame()) {
1832         ec = INVALID_ACCESS_ERR;
1833         return String();
1834     }
1835
1836     LayerTreeFlags layerTreeFlags = 0;
1837     if (flags & LAYER_TREE_INCLUDES_VISIBLE_RECTS)
1838         layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
1839     if (flags & LAYER_TREE_INCLUDES_TILE_CACHES)
1840         layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
1841     if (flags & LAYER_TREE_INCLUDES_REPAINT_RECTS)
1842         layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
1843     if (flags & LAYER_TREE_INCLUDES_PAINTING_PHASES)
1844         layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
1845     if (flags & LAYER_TREE_INCLUDES_CONTENT_LAYERS)
1846         layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
1847
1848     return document->frame()->layerTreeAsText(layerTreeFlags);
1849 }
1850
1851 String Internals::repaintRectsAsText(ExceptionCode& ec) const
1852 {
1853     Document* document = contextDocument();
1854     if (!document || !document->frame()) {
1855         ec = INVALID_ACCESS_ERR;
1856         return String();
1857     }
1858
1859     return document->frame()->trackedRepaintRectsAsText();
1860 }
1861
1862 String Internals::scrollingStateTreeAsText(ExceptionCode& ec) const
1863 {
1864     Document* document = contextDocument();
1865     if (!document || !document->frame()) {
1866         ec = INVALID_ACCESS_ERR;
1867         return String();
1868     }
1869
1870     Page* page = document->page();
1871     if (!page)
1872         return String();
1873
1874     return page->scrollingStateTreeAsText();
1875 }
1876
1877 String Internals::mainThreadScrollingReasons(ExceptionCode& ec) const
1878 {
1879     Document* document = contextDocument();
1880     if (!document || !document->frame()) {
1881         ec = INVALID_ACCESS_ERR;
1882         return String();
1883     }
1884
1885     Page* page = document->page();
1886     if (!page)
1887         return String();
1888
1889     return page->synchronousScrollingReasonsAsText();
1890 }
1891
1892 RefPtr<ClientRectList> Internals::nonFastScrollableRects(ExceptionCode& ec) const
1893 {
1894     Document* document = contextDocument();
1895     if (!document || !document->frame()) {
1896         ec = INVALID_ACCESS_ERR;
1897         return nullptr;
1898     }
1899
1900     Page* page = document->page();
1901     if (!page)
1902         return nullptr;
1903
1904     return page->nonFastScrollableRects();
1905 }
1906
1907 void Internals::garbageCollectDocumentResources(ExceptionCode& ec) const
1908 {
1909     Document* document = contextDocument();
1910     if (!document) {
1911         ec = INVALID_ACCESS_ERR;
1912         return;
1913     }
1914     document->cachedResourceLoader().garbageCollectDocumentResources();
1915 }
1916
1917 void Internals::allowRoundingHacks() const
1918 {
1919     TextRun::setAllowsRoundingHacks(true);
1920 }
1921
1922 void Internals::insertAuthorCSS(const String& css, ExceptionCode& ec) const
1923 {
1924     Document* document = contextDocument();
1925     if (!document) {
1926         ec = INVALID_ACCESS_ERR;
1927         return;
1928     }
1929
1930     auto parsedSheet = StyleSheetContents::create(*document);
1931     parsedSheet.get().setIsUserStyleSheet(false);
1932     parsedSheet.get().parseString(css);
1933     document->styleSheetCollection().addAuthorSheet(WTF::move(parsedSheet));
1934 }
1935
1936 void Internals::insertUserCSS(const String& css, ExceptionCode& ec) const
1937 {
1938     Document* document = contextDocument();
1939     if (!document) {
1940         ec = INVALID_ACCESS_ERR;
1941         return;
1942     }
1943
1944     auto parsedSheet = StyleSheetContents::create(*document);
1945     parsedSheet.get().setIsUserStyleSheet(true);
1946     parsedSheet.get().parseString(css);
1947     document->styleSheetCollection().addUserSheet(WTF::move(parsedSheet));
1948 }
1949
1950 String Internals::counterValue(Element* element)
1951 {
1952     if (!element)
1953         return String();
1954
1955     return counterValueForElement(element);
1956 }
1957
1958 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1959 {
1960     if (!element)
1961         return 0;
1962
1963     return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1964 }
1965
1966 Vector<String> Internals::shortcutIconURLs() const
1967 {
1968     Vector<String> vector;
1969
1970     if (!frame())
1971         return vector;
1972
1973     auto string = frame()->loader().icon().url().string();
1974     if (!string.isNull())
1975         vector.append(string);
1976     return vector;
1977 }
1978
1979 int Internals::numberOfPages(float pageWidth, float pageHeight)
1980 {
1981     if (!frame())
1982         return -1;
1983
1984     return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
1985 }
1986
1987 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionCode& ec) const
1988 {
1989     if (!frame()) {
1990         ec = INVALID_ACCESS_ERR;
1991         return String();
1992     }
1993
1994     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
1995 }
1996
1997 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionCode& ec) const
1998 {
1999     if (!frame()) {
2000         ec = INVALID_ACCESS_ERR;
2001         return String();
2002     }
2003
2004     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
2005 }
2006
2007 void Internals::setPageScaleFactor(float scaleFactor, int x, int y, ExceptionCode& ec)
2008 {
2009     Document* document = contextDocument();
2010     if (!document || !document->page()) {
2011         ec = INVALID_ACCESS_ERR;
2012         return;
2013     }
2014     Page* page = document->page();
2015     page->setPageScaleFactor(scaleFactor, IntPoint(x, y));
2016 }
2017
2018 void Internals::setPageZoomFactor(float zoomFactor, ExceptionCode& ec)
2019 {
2020     Document* document = contextDocument();
2021     if (!document || !document->frame()) {
2022         ec = INVALID_ACCESS_ERR;
2023         return;
2024     }
2025     Frame* frame = document->frame();
2026     frame->setPageZoomFactor(zoomFactor);
2027 }
2028
2029 void Internals::setTextZoomFactor(float zoomFactor, ExceptionCode& ec)
2030 {
2031     Document* document = contextDocument();
2032     if (!document || !document->frame()) {
2033         ec = INVALID_ACCESS_ERR;
2034         return;
2035     }
2036     Frame* frame = document->frame();
2037     frame->setTextZoomFactor(zoomFactor);
2038 }
2039
2040 void Internals::setUseFixedLayout(bool useFixedLayout, ExceptionCode& ec)
2041 {
2042     Document* document = contextDocument();
2043     if (!document || !document->view()) {
2044         ec = INVALID_ACCESS_ERR;
2045         return;
2046     }
2047     FrameView* frameView = document->view();
2048     frameView->setUseFixedLayout(useFixedLayout);
2049 }
2050
2051 void Internals::setFixedLayoutSize(int width, int height, ExceptionCode& ec)
2052 {
2053     Document* document = contextDocument();
2054     if (!document || !document->view()) {
2055         ec = INVALID_ACCESS_ERR;
2056         return;
2057     }
2058     FrameView* frameView = document->view();
2059     frameView->setFixedLayoutSize(IntSize(width, height));
2060 }
2061
2062 void Internals::setHeaderHeight(float height)
2063 {
2064     Document* document = contextDocument();
2065     if (!document || !document->view())
2066         return;
2067
2068     FrameView* frameView = document->view();
2069     frameView->setHeaderHeight(height);
2070 }
2071
2072 void Internals::setFooterHeight(float height)
2073 {
2074     Document* document = contextDocument();
2075     if (!document || !document->view())
2076         return;
2077
2078     FrameView* frameView = document->view();
2079     frameView->setFooterHeight(height);
2080 }
2081     
2082 void Internals::setTopContentInset(float contentInset)
2083 {
2084     Document* document = contextDocument();
2085     if (!document)
2086         return;
2087     
2088     Page* page = document->page();
2089     page->setTopContentInset(contentInset);
2090 }
2091
2092 #if ENABLE(FULLSCREEN_API)
2093 void Internals::webkitWillEnterFullScreenForElement(Element* element)
2094 {
2095     Document* document = contextDocument();
2096     if (!document)
2097         return;
2098     document->webkitWillEnterFullScreenForElement(element);
2099 }
2100
2101 void Internals::webkitDidEnterFullScreenForElement(Element* element)
2102 {
2103     Document* document = contextDocument();
2104     if (!document)
2105         return;
2106     document->webkitDidEnterFullScreenForElement(element);
2107 }
2108
2109 void Internals::webkitWillExitFullScreenForElement(Element* element)
2110 {
2111     Document* document = contextDocument();
2112     if (!document)
2113         return;
2114     document->webkitWillExitFullScreenForElement(element);
2115 }
2116
2117 void Internals::webkitDidExitFullScreenForElement(Element* element)
2118 {
2119     Document* document = contextDocument();
2120     if (!document)
2121         return;
2122     document->webkitDidExitFullScreenForElement(element);
2123 }
2124 #endif
2125
2126 void Internals::setApplicationCacheOriginQuota(unsigned long long quota)
2127 {
2128     Document* document = contextDocument();
2129     if (!document)
2130         return;
2131     ApplicationCacheStorage::singleton().storeUpdatedQuotaForOrigin(document->securityOrigin(), quota);
2132 }
2133
2134 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
2135 {
2136     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2137 }
2138
2139 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
2140 {
2141     SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
2142 }
2143
2144 PassRefPtr<MallocStatistics> Internals::mallocStatistics() const
2145 {
2146     return MallocStatistics::create();
2147 }
2148
2149 PassRefPtr<TypeConversions> Internals::typeConversions() const
2150 {
2151     return TypeConversions::create();
2152 }
2153
2154 PassRefPtr<MemoryInfo> Internals::memoryInfo() const
2155 {
2156     return MemoryInfo::create();
2157 }
2158
2159 Vector<String> Internals::getReferencedFilePaths() const
2160 {
2161     frame()->loader().history().saveDocumentAndScrollState();
2162     return FormController::getReferencedFilePaths(frame()->loader().history().currentItem()->documentState());
2163 }
2164
2165 void Internals::startTrackingRepaints(ExceptionCode& ec)
2166 {
2167     Document* document = contextDocument();
2168     if (!document || !document->view()) {
2169         ec = INVALID_ACCESS_ERR;
2170         return;
2171     }
2172
2173     FrameView* frameView = document->view();
2174     frameView->setTracksRepaints(true);
2175 }
2176
2177 void Internals::stopTrackingRepaints(ExceptionCode& ec)
2178 {
2179     Document* document = contextDocument();
2180     if (!document || !document->view()) {
2181         ec = INVALID_ACCESS_ERR;
2182         return;
2183     }
2184
2185     FrameView* frameView = document->view();
2186     frameView->setTracksRepaints(false);
2187 }
2188
2189 void Internals::startTrackingLayerFlushes(ExceptionCode& ec)
2190 {
2191     Document* document = contextDocument();
2192     if (!document || !document->renderView()) {
2193         ec = INVALID_ACCESS_ERR;
2194         return;
2195     }
2196
2197     document->renderView()->compositor().startTrackingLayerFlushes();
2198 }
2199
2200 unsigned long Internals::layerFlushCount(ExceptionCode& ec)
2201 {
2202     Document* document = contextDocument();
2203     if (!document || !document->renderView()) {
2204         ec = INVALID_ACCESS_ERR;
2205         return 0;
2206     }
2207
2208     return document->renderView()->compositor().layerFlushCount();
2209 }
2210
2211 void Internals::startTrackingStyleRecalcs(ExceptionCode& ec)
2212 {
2213     Document* document = contextDocument();
2214     if (!document) {
2215         ec = INVALID_ACCESS_ERR;
2216         return;
2217     }
2218     document->startTrackingStyleRecalcs();
2219 }
2220
2221 unsigned long Internals::styleRecalcCount(ExceptionCode& ec)
2222 {
2223     Document* document = contextDocument();
2224     if (!document) {
2225         ec = INVALID_ACCESS_ERR;
2226         return 0;
2227     }
2228     
2229     return document->styleRecalcCount();
2230 }
2231
2232 void Internals::startTrackingCompositingUpdates(ExceptionCode& ec)
2233 {
2234     Document* document = contextDocument();
2235     if (!document || !document->renderView()) {
2236         ec = INVALID_ACCESS_ERR;
2237         return;
2238     }
2239
2240     document->renderView()->compositor().startTrackingCompositingUpdates();
2241 }
2242
2243 unsigned long Internals::compositingUpdateCount(ExceptionCode& ec)
2244 {
2245     Document* document = contextDocument();
2246     if (!document || !document->renderView()) {
2247         ec = INVALID_ACCESS_ERR;
2248         return 0;
2249     }
2250     
2251     return document->renderView()->compositor().compositingUpdateCount();
2252 }
2253
2254 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(ExceptionCode& ec)
2255 {
2256     updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(nullptr, ec);
2257 }
2258
2259 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionCode& ec)
2260 {
2261     Document* document;
2262     if (!node)
2263         document = contextDocument();
2264     else if (is<Document>(*node))
2265         document = downcast<Document>(node);
2266     else if (is<HTMLIFrameElement>(*node))
2267         document = downcast<HTMLIFrameElement>(*node).contentDocument();
2268     else {
2269         ec = TypeError;
2270         return;
2271     }
2272
2273     document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
2274 }
2275
2276 unsigned Internals::layoutCount() const
2277 {
2278     Document* document = contextDocument();
2279     if (!document || !document->view())
2280         return 0;
2281     return document->view()->layoutCount();
2282 }
2283
2284 #if !PLATFORM(IOS)
2285 static const char* cursorTypeToString(Cursor::Type cursorType)
2286 {
2287     switch (cursorType) {
2288     case Cursor::Pointer: return "Pointer";
2289     case Cursor::Cross: return "Cross";
2290     case Cursor::Hand: return "Hand";
2291     case Cursor::IBeam: return "IBeam";
2292     case Cursor::Wait: return "Wait";
2293     case Cursor::Help: return "Help";
2294     case Cursor::EastResize: return "EastResize";
2295     case Cursor::NorthResize: return "NorthResize";
2296     case Cursor::NorthEastResize: return "NorthEastResize";
2297     case Cursor::NorthWestResize: return "NorthWestResize";
2298     case Cursor::SouthResize: return "SouthResize";
2299     case Cursor::SouthEastResize: return "SouthEastResize";
2300     case Cursor::SouthWestResize: return "SouthWestResize";
2301     case Cursor::WestResize: return "WestResize";
2302     case Cursor::NorthSouthResize: return "NorthSouthResize";
2303     case Cursor::EastWestResize: return "EastWestResize";
2304     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
2305     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
2306     case Cursor::ColumnResize: return "ColumnResize";
2307     case Cursor::RowResize: return "RowResize";
2308     case Cursor::MiddlePanning: return "MiddlePanning";
2309     case Cursor::EastPanning: return "EastPanning";
2310     case Cursor::NorthPanning: return "NorthPanning";
2311     case Cursor::NorthEastPanning: return "NorthEastPanning";
2312     case Cursor::NorthWestPanning: return "NorthWestPanning";
2313     case Cursor::SouthPanning: return "SouthPanning";
2314     case Cursor::SouthEastPanning: return "SouthEastPanning";
2315     case Cursor::SouthWestPanning: return "SouthWestPanning";
2316     case Cursor::WestPanning: return "WestPanning";
2317     case Cursor::Move: return "Move";
2318     case Cursor::VerticalText: return "VerticalText";
2319     case Cursor::Cell: return "Cell";
2320     case Cursor::ContextMenu: return "ContextMenu";
2321     case Cursor::Alias: return "Alias";
2322     case Cursor::Progress: return "Progress";
2323     case Cursor::NoDrop: return "NoDrop";
2324     case Cursor::Copy: return "Copy";
2325     case Cursor::None: return "None";
2326     case Cursor::NotAllowed: return "NotAllowed";
2327     case Cursor::ZoomIn: return "ZoomIn";
2328     case Cursor::ZoomOut: return "ZoomOut";
2329     case Cursor::Grab: return "Grab";
2330     case Cursor::Grabbing: return "Grabbing";
2331     case Cursor::Custom: return "Custom";
2332     }
2333
2334     ASSERT_NOT_REACHED();
2335     return "UNKNOWN";
2336 }
2337 #endif
2338
2339 String Internals::getCurrentCursorInfo(ExceptionCode& ec)
2340 {
2341     Document* document = contextDocument();
2342     if (!document || !document->frame()) {
2343         ec = INVALID_ACCESS_ERR;
2344         return String();
2345     }
2346
2347 #if !PLATFORM(IOS)
2348     Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
2349
2350     StringBuilder result;
2351     result.appendLiteral("type=");
2352     result.append(cursorTypeToString(cursor.type()));
2353     result.appendLiteral(" hotSpot=");
2354     result.appendNumber(cursor.hotSpot().x());
2355     result.append(',');
2356     result.appendNumber(cursor.hotSpot().y());
2357     if (cursor.image()) {
2358         FloatSize size = cursor.image()->size();
2359         result.appendLiteral(" image=");
2360         result.appendNumber(size.width());
2361         result.append('x');
2362         result.appendNumber(size.height());
2363     }
2364 #if ENABLE(MOUSE_CURSOR_SCALE)
2365     if (cursor.imageScaleFactor() != 1) {
2366         result.appendLiteral(" scale=");
2367         NumberToStringBuffer buffer;
2368         result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
2369     }
2370 #endif
2371     return result.toString();
2372 #else
2373     return "FAIL: Cursor details not available on this platform.";
2374 #endif
2375 }
2376
2377 PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
2378 {
2379     Vector<uint8_t> bytes = value->data();
2380     return ArrayBuffer::create(bytes.data(), bytes.size());
2381 }
2382
2383 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
2384 {
2385     Vector<uint8_t> bytes;
2386     bytes.append(static_cast<const uint8_t*>(buffer->data()), buffer->byteLength());
2387     return SerializedScriptValue::adopt(bytes);
2388 }
2389
2390 bool Internals::isFromCurrentWorld(Deprecated::ScriptValue value) const
2391 {
2392     ASSERT(!value.hasNoValue());
2393     
2394     JSC::ExecState* exec = contextDocument()->vm().topCallFrame;
2395     if (!value.isObject() || &worldForDOMObject(value.jsValue().getObject()) == &currentWorld(exec))
2396         return true;
2397     return false;
2398 }
2399
2400 void Internals::setUsesOverlayScrollbars(bool enabled)
2401 {
2402     WebCore::Settings::setUsesOverlayScrollbars(enabled);
2403 }
2404
2405 void Internals::forceReload(bool endToEnd)
2406 {
2407     frame()->loader().reload(endToEnd);
2408 }
2409
2410 #if ENABLE(ENCRYPTED_MEDIA_V2)
2411 void Internals::initializeMockCDM()
2412 {
2413     CDM::registerCDMFactory([](CDM* cdm) { return std::make_unique<MockCDM>(cdm); },
2414         MockCDM::supportsKeySystem, MockCDM::supportsKeySystemAndMimeType);
2415 }
2416 #endif
2417
2418 String Internals::markerTextForListItem(Element* element, ExceptionCode& ec)
2419 {
2420     if (!element) {
2421         ec = INVALID_ACCESS_ERR;
2422         return String();
2423     }
2424     return WebCore::markerTextForListItem(element);
2425 }
2426
2427 String Internals::toolTipFromElement(Element* element, ExceptionCode& ec) const
2428 {
2429     if (!element) {
2430         ec = INVALID_ACCESS_ERR;
2431         return String();
2432     }
2433     HitTestResult result;
2434     result.setInnerNode(element);
2435     TextDirection dir;
2436     return result.title(dir);
2437 }
2438
2439 String Internals::getImageSourceURL(Element* element, ExceptionCode& ec)
2440 {
2441     if (!element) {
2442         ec = INVALID_ACCESS_ERR;
2443         return String();
2444     }
2445     return element->imageSourceURL();
2446 }
2447
2448 #if ENABLE(VIDEO)
2449 void Internals::simulateAudioInterruption(Node* node)
2450 {
2451 #if USE(GSTREAMER)
2452     HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2453     element->player()->simulateAudioInterruption();
2454 #else
2455     UNUSED_PARAM(node);
2456 #endif
2457 }
2458
2459 bool Internals::mediaElementHasCharacteristic(Node* node, const String& characteristic, ExceptionCode& ec)
2460 {
2461     if (!is<HTMLMediaElement>(*node))
2462         return false;
2463
2464     HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2465
2466     if (equalIgnoringCase(characteristic, "Audible"))
2467         return element->hasAudio();
2468     if (equalIgnoringCase(characteristic, "Visual"))
2469         return element->hasVideo();
2470     if (equalIgnoringCase(characteristic, "Legible"))
2471         return element->hasClosedCaptions();
2472
2473     ec = SYNTAX_ERR;
2474     return false;
2475 }
2476 #endif
2477
2478 bool Internals::isSelectPopupVisible(Node* node)
2479 {
2480     if (!is<HTMLSelectElement>(*node))
2481         return false;
2482
2483     HTMLSelectElement& select = downcast<HTMLSelectElement>(*node);
2484
2485     auto* renderer = select.renderer();
2486     ASSERT(renderer);
2487     if (!is<RenderMenuList>(*renderer))
2488         return false;
2489
2490 #if !PLATFORM(IOS)
2491     return downcast<RenderMenuList>(*renderer).popupIsVisible();
2492 #else
2493     return false;
2494 #endif // !PLATFORM(IOS)
2495 }
2496
2497 String Internals::captionsStyleSheetOverride(ExceptionCode& ec)
2498 {
2499     Document* document = contextDocument();
2500     if (!document || !document->page()) {
2501         ec = INVALID_ACCESS_ERR;
2502         return emptyString();
2503     }
2504
2505 #if ENABLE(VIDEO_TRACK)
2506     return document->page()->group().captionPreferences()->captionsStyleSheetOverride();
2507 #else
2508     return emptyString();
2509 #endif
2510 }
2511
2512 void Internals::setCaptionsStyleSheetOverride(const String& override, ExceptionCode& ec)
2513 {
2514     Document* document = contextDocument();
2515     if (!document || !document->page()) {
2516         ec = INVALID_ACCESS_ERR;
2517         return;
2518     }
2519
2520 #if ENABLE(VIDEO_TRACK)
2521     document->page()->group().captionPreferences()->setCaptionsStyleSheetOverride(override);
2522 #else
2523     UNUSED_PARAM(override);
2524 #endif
2525 }
2526
2527 void Internals::setPrimaryAudioTrackLanguageOverride(const String& language, ExceptionCode& ec)
2528 {
2529     Document* document = contextDocument();
2530     if (!document || !document->page()) {
2531         ec = INVALID_ACCESS_ERR;
2532         return;
2533     }
2534
2535 #if ENABLE(VIDEO_TRACK)
2536     document->page()->group().captionPreferences()->setPrimaryAudioTrackLanguageOverride(language);
2537 #else
2538     UNUSED_PARAM(language);
2539 #endif
2540 }
2541
2542 void Internals::setCaptionDisplayMode(const String& mode, ExceptionCode& ec)
2543 {
2544     Document* document = contextDocument();
2545     if (!document || !document->page()) {
2546         ec = INVALID_ACCESS_ERR;
2547         return;
2548     }
2549     
2550 #if ENABLE(VIDEO_TRACK)
2551     CaptionUserPreferences* captionPreferences = document->page()->group().captionPreferences();
2552     
2553     if (equalIgnoringCase(mode, "Automatic"))
2554         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::Automatic);
2555     else if (equalIgnoringCase(mode, "ForcedOnly"))
2556         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
2557     else if (equalIgnoringCase(mode, "AlwaysOn"))
2558         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn);
2559     else
2560         ec = SYNTAX_ERR;
2561 #else
2562     UNUSED_PARAM(mode);
2563 #endif
2564 }
2565
2566 #if ENABLE(VIDEO)
2567 PassRefPtr<TimeRanges> Internals::createTimeRanges(Float32Array* startTimes, Float32Array* endTimes)
2568 {
2569     ASSERT(startTimes && endTimes);
2570     ASSERT(startTimes->length() == endTimes->length());
2571     RefPtr<TimeRanges> ranges = TimeRanges::create();
2572
2573     unsigned count = std::min(startTimes->length(), endTimes->length());
2574     for (unsigned i = 0; i < count; ++i)
2575         ranges->add(startTimes->item(i), endTimes->item(i));
2576     return ranges;
2577 }
2578
2579 double Internals::closestTimeToTimeRanges(double time, TimeRanges* ranges)
2580 {
2581     return ranges->nearest(time);
2582 }
2583 #endif
2584
2585 Ref<ClientRect> Internals::selectionBounds(ExceptionCode& ec)
2586 {
2587     Document* document = contextDocument();
2588     if (!document || !document->frame()) {
2589         ec = INVALID_ACCESS_ERR;
2590         return ClientRect::create();
2591     }
2592
2593     return ClientRect::create(document->frame()->selection().selectionBounds());
2594 }
2595
2596 #if ENABLE(VIBRATION)
2597 bool Internals::isVibrating()
2598 {
2599     Page* page = contextDocument()->page();
2600     ASSERT(page);
2601
2602     return Vibration::from(page)->isVibrating();
2603 }
2604 #endif
2605
2606 bool Internals::isPluginUnavailabilityIndicatorObscured(Element* element, ExceptionCode& ec)
2607 {
2608     if (!element) {
2609         ec = INVALID_ACCESS_ERR;
2610         return false;
2611     }
2612
2613     auto* renderer = element->renderer();
2614     if (!is<RenderEmbeddedObject>(renderer)) {
2615         ec = INVALID_ACCESS_ERR;
2616         return false;
2617     }
2618
2619     return downcast<RenderEmbeddedObject>(*renderer).isReplacementObscured();
2620 }
2621     
2622 bool Internals::isPluginSnapshotted(Element* element, ExceptionCode& ec)
2623 {
2624     if (!element) {
2625         ec = INVALID_ACCESS_ERR;
2626         return false;
2627     }
2628     HTMLPlugInElement* pluginElement = downcast<HTMLPlugInElement>(element);
2629     return pluginElement->displayState() <= HTMLPlugInElement::DisplayingSnapshot;
2630 }
2631     
2632 #if ENABLE(MEDIA_SOURCE)
2633 void Internals::initializeMockMediaSource()
2634 {
2635 #if USE(AVFOUNDATION)
2636     WebCore::Settings::setAVFoundationEnabled(false);
2637 #endif
2638     MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
2639 }
2640
2641 Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer* buffer, const AtomicString& trackID)
2642 {
2643     if (!buffer)
2644         return Vector<String>();
2645
2646     return buffer->bufferedSamplesForTrackID(trackID);
2647 }
2648     
2649 void Internals::setShouldGenerateTimestamps(SourceBuffer* buffer, bool flag)
2650 {
2651     if (buffer)
2652         buffer->setShouldGenerateTimestamps(flag);
2653 }
2654 #endif
2655
2656 #if ENABLE(VIDEO)
2657 void Internals::beginMediaSessionInterruption()
2658 {
2659     PlatformMediaSessionManager::sharedManager().beginInterruption(PlatformMediaSession::SystemInterruption);
2660 }
2661
2662 void Internals::endMediaSessionInterruption(const String& flagsString)
2663 {
2664     PlatformMediaSession::EndInterruptionFlags flags = PlatformMediaSession::NoFlags;
2665
2666     if (equalIgnoringCase(flagsString, "MayResumePlaying"))
2667         flags = PlatformMediaSession::MayResumePlaying;
2668     
2669     PlatformMediaSessionManager::sharedManager().endInterruption(flags);
2670 }
2671
2672 void Internals::applicationWillEnterForeground() const
2673 {
2674     PlatformMediaSessionManager::sharedManager().applicationWillEnterForeground();
2675 }
2676
2677 void Internals::applicationWillEnterBackground() const
2678 {
2679     PlatformMediaSessionManager::sharedManager().applicationWillEnterBackground();
2680 }
2681
2682 void Internals::setMediaSessionRestrictions(const String& mediaTypeString, const String& restrictionsString, ExceptionCode& ec)
2683 {
2684     PlatformMediaSession::MediaType mediaType = PlatformMediaSession::None;
2685     if (equalIgnoringCase(mediaTypeString, "Video"))
2686         mediaType = PlatformMediaSession::Video;
2687     else if (equalIgnoringCase(mediaTypeString, "Audio"))
2688         mediaType = PlatformMediaSession::Audio;
2689     else if (equalIgnoringCase(mediaTypeString, "WebAudio"))
2690         mediaType = PlatformMediaSession::WebAudio;
2691     else {
2692         ec = INVALID_ACCESS_ERR;
2693         return;
2694     }
2695
2696     PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
2697     PlatformMediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions);
2698
2699     restrictions = PlatformMediaSessionManager::NoRestrictions;
2700
2701     Vector<String> restrictionsArray;
2702     restrictionsString.split(',', false, restrictionsArray);
2703     for (auto& restrictionString : restrictionsArray) {
2704         if (equalIgnoringCase(restrictionString, "ConcurrentPlaybackNotPermitted"))
2705             restrictions |= PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted;
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         if (equalIgnoringCase(restrictionString, "MetadataPreloadingNotPermitted"))
2752             restrictions |= MediaElementSession::MetadataPreloadingNotPermitted;
2753         if (equalIgnoringCase(restrictionString, "AutoPreloadingNotPermitted"))
2754             restrictions |= MediaElementSession::AutoPreloadingNotPermitted;
2755     }
2756     element->mediaSession().addBehaviorRestriction(restrictions);
2757 }
2758
2759 void Internals::postRemoteControlCommand(const String& commandString, ExceptionCode& ec)
2760 {
2761     PlatformMediaSession::RemoteControlCommandType command;
2762     
2763     if (equalIgnoringCase(commandString, "Play"))
2764         command = PlatformMediaSession::PlayCommand;
2765     else if (equalIgnoringCase(commandString, "Pause"))
2766         command = PlatformMediaSession::PauseCommand;
2767     else if (equalIgnoringCase(commandString, "Stop"))
2768         command = PlatformMediaSession::StopCommand;
2769     else if (equalIgnoringCase(commandString, "TogglePlayPause"))
2770         command = PlatformMediaSession::TogglePlayPauseCommand;
2771     else if (equalIgnoringCase(commandString, "BeginSeekingBackward"))
2772         command = PlatformMediaSession::BeginSeekingBackwardCommand;
2773     else if (equalIgnoringCase(commandString, "EndSeekingBackward"))
2774         command = PlatformMediaSession::EndSeekingBackwardCommand;
2775     else if (equalIgnoringCase(commandString, "BeginSeekingForward"))
2776         command = PlatformMediaSession::BeginSeekingForwardCommand;
2777     else if (equalIgnoringCase(commandString, "EndSeekingForward"))
2778         command = PlatformMediaSession::EndSeekingForwardCommand;
2779     else {
2780         ec = INVALID_ACCESS_ERR;
2781         return;
2782     }
2783     
2784     PlatformMediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command);
2785 }
2786
2787 bool Internals::elementIsBlockingDisplaySleep(Element* element) const
2788 {
2789     HTMLMediaElement* mediaElement = downcast<HTMLMediaElement>(element);
2790     return mediaElement ? mediaElement->isDisablingSleep() : false;
2791 }
2792
2793 #endif // ENABLE(VIDEO)
2794
2795 #if ENABLE(MEDIA_SESSION)
2796 static MediaSessionInterruptingCategory interruptingCategoryFromString(const String& interruptingCategoryString)
2797 {
2798     if (interruptingCategoryString == "content")
2799         return MediaSessionInterruptingCategory::Content;
2800     if (interruptingCategoryString == "transient")
2801         return MediaSessionInterruptingCategory::Transient;
2802     if (interruptingCategoryString == "transient-solo")
2803         return MediaSessionInterruptingCategory::TransientSolo;
2804     ASSERT_NOT_REACHED();
2805     return MediaSessionInterruptingCategory::Content;
2806 }
2807
2808 void Internals::sendMediaSessionStartOfInterruptionNotification(const String& interruptingCategoryString)
2809 {
2810     MediaSessionManager::singleton().didReceiveStartOfInterruptionNotification(interruptingCategoryFromString(interruptingCategoryString));
2811 }
2812
2813 void Internals::sendMediaSessionEndOfInterruptionNotification(const String& interruptingCategoryString)
2814 {
2815     MediaSessionManager::singleton().didReceiveEndOfInterruptionNotification(interruptingCategoryFromString(interruptingCategoryString));
2816 }
2817
2818 String Internals::mediaSessionCurrentState(MediaSession* session) const
2819 {
2820     switch (session->currentState()) {
2821     case MediaSession::State::Active:
2822         return "active";
2823     case MediaSession::State::Interrupted:
2824         return "interrupted";
2825     case MediaSession::State::Idle:
2826         return "idle";
2827     }
2828 }
2829
2830 double Internals::mediaElementPlayerVolume(HTMLMediaElement* element) const
2831 {
2832     ASSERT_ARG(element, element);
2833     return element->playerVolume();
2834 }
2835
2836 void Internals::sendMediaControlEvent(const String& event)
2837 {
2838     if (event == "play-pause")
2839         MediaSessionManager::singleton().togglePlayback();
2840     else if (event == "next-track")
2841         MediaSessionManager::singleton().skipToNextTrack();
2842     else if (event == "previous-track")
2843         MediaSessionManager::singleton().skipToPreviousTrack();
2844     else
2845         ASSERT_NOT_REACHED();
2846 }
2847 #endif // ENABLE(MEDIA_SESSION)
2848
2849 #if ENABLE(WEB_AUDIO)
2850 void Internals::setAudioContextRestrictions(AudioContext* context, const String &restrictionsString, ExceptionCode &ec)
2851 {
2852     if (!context) {
2853         ec = INVALID_ACCESS_ERR;
2854         return;
2855     }
2856
2857     AudioContext::BehaviorRestrictions restrictions = context->behaviorRestrictions();
2858     context->removeBehaviorRestriction(restrictions);
2859
2860     restrictions = MediaElementSession::NoRestrictions;
2861
2862     Vector<String> restrictionsArray;
2863     restrictionsString.split(',', false, restrictionsArray);
2864     for (auto& restrictionString : restrictionsArray) {
2865         if (equalIgnoringCase(restrictionString, "NoRestrictions"))
2866             restrictions |= AudioContext::NoRestrictions;
2867         if (equalIgnoringCase(restrictionString, "RequireUserGestureForAudioStart"))
2868             restrictions |= AudioContext::RequireUserGestureForAudioStartRestriction;
2869         if (equalIgnoringCase(restrictionString, "RequirePageConsentForAudioStart"))
2870             restrictions |= AudioContext::RequirePageConsentForAudioStartRestriction;
2871     }
2872     context->addBehaviorRestriction(restrictions);
2873 }
2874 #endif
2875
2876 void Internals::simulateSystemSleep() const
2877 {
2878 #if ENABLE(VIDEO)
2879     PlatformMediaSessionManager::sharedManager().systemWillSleep();
2880 #endif
2881 }
2882
2883 void Internals::simulateSystemWake() const
2884 {
2885 #if ENABLE(VIDEO)
2886     PlatformMediaSessionManager::sharedManager().systemDidWake();
2887 #endif
2888 }
2889
2890
2891 void Internals::installMockPageOverlay(const String& overlayType, ExceptionCode& ec)
2892 {
2893     Document* document = contextDocument();
2894     if (!document || !document->frame()) {
2895         ec = INVALID_ACCESS_ERR;
2896         return;
2897     }
2898
2899     MockPageOverlayClient::singleton().installOverlay(document->frame()->mainFrame(), overlayType == "view" ? PageOverlay::OverlayType::View : PageOverlay::OverlayType::Document);
2900 }
2901
2902 String Internals::pageOverlayLayerTreeAsText(ExceptionCode& ec) const
2903 {
2904     Document* document = contextDocument();
2905     if (!document || !document->frame()) {
2906         ec = INVALID_ACCESS_ERR;
2907         return String();
2908     }
2909
2910     document->updateLayout();
2911
2912     return MockPageOverlayClient::singleton().layerTreeAsText(document->frame()->mainFrame());
2913 }
2914
2915 void Internals::setPageMuted(bool muted)
2916 {
2917     Document* document = contextDocument();
2918     if (!document)
2919         return;
2920
2921     if (Page* page = document->page())
2922         page->setMuted(muted);
2923 }
2924
2925 bool Internals::isPagePlayingAudio()
2926 {
2927     Document* document = contextDocument();
2928     if (!document || !document->page())
2929         return false;
2930
2931     return !!(document->page()->mediaState() & MediaProducer::IsPlayingAudio);
2932 }
2933
2934 RefPtr<File> Internals::createFile(const String& path)
2935 {
2936     Document* document = contextDocument();
2937     if (!document)
2938         return nullptr;
2939
2940     URL url = document->completeURL(path);
2941     if (!url.isLocalFile())
2942         return nullptr;
2943
2944     return File::create(url.fileSystemPath());
2945 }
2946
2947 void Internals::queueMicroTask(int testNumber)
2948 {
2949     if (contextDocument())
2950         MicroTaskQueue::singleton().queueMicroTask(std::make_unique<MicroTaskTest>(contextDocument()->createWeakPtr(), testNumber));
2951 }
2952
2953 #if ENABLE(CONTENT_FILTERING)
2954 MockContentFilterSettings& Internals::mockContentFilterSettings()
2955 {
2956     return MockContentFilterSettings::singleton();
2957 }
2958 #endif
2959
2960 #if ENABLE(CSS_SCROLL_SNAP)
2961 static void appendOffsets(StringBuilder& builder, const Vector<LayoutUnit>& snapOffsets)
2962 {
2963     bool justStarting = true;
2964
2965     builder.append("{ ");
2966     for (auto& coordinate : snapOffsets) {
2967         if (!justStarting)
2968             builder.append(", ");
2969         else
2970             justStarting = false;
2971         
2972         builder.append(String::number(coordinate.toUnsigned()));
2973     }
2974     builder.append(" }");
2975 }
2976     
2977 String Internals::scrollSnapOffsets(Element* element, ExceptionCode& ec)
2978 {
2979     if (!element) {
2980         ec = INVALID_ACCESS_ERR;
2981         return String();
2982     }
2983
2984     if (!element->renderBox())
2985         return String();
2986
2987     RenderBox& box = *element->renderBox();
2988     ScrollableArea* scrollableArea;
2989     
2990     if (box.isBody()) {
2991         FrameView* frameView = box.frame().mainFrame().view();
2992         if (!frameView || !frameView->isScrollable()) {
2993             ec = INVALID_ACCESS_ERR;
2994             return String();
2995         }
2996         scrollableArea = frameView;
2997         
2998     } else {
2999         if (!box.canBeScrolledAndHasScrollableArea()) {
3000             ec = INVALID_ACCESS_ERR;
3001             return String();
3002         }
3003         scrollableArea = box.layer();
3004     }
3005
3006     if (!scrollableArea)
3007         return String();
3008     
3009     StringBuilder result;
3010
3011     if (scrollableArea->horizontalSnapOffsets()) {
3012         result.append("horizontal = ");
3013         appendOffsets(result, *scrollableArea->horizontalSnapOffsets());
3014     }
3015
3016     if (scrollableArea->verticalSnapOffsets()) {
3017         if (result.length())
3018             result.append(", ");
3019
3020         result.append("vertical = ");
3021         appendOffsets(result, *scrollableArea->verticalSnapOffsets());
3022     }
3023
3024     return result.toString();
3025 }
3026 #endif
3027
3028 bool Internals::testPreloaderSettingViewport()
3029 {
3030     return testPreloadScannerViewportSupport(contextDocument());
3031 }
3032
3033 String Internals::pathStringWithShrinkWrappedRects(Vector<double> rectComponents, double radius, ExceptionCode& ec)
3034 {
3035     if (rectComponents.size() % 4) {
3036         ec = INVALID_ACCESS_ERR;
3037         return String();
3038     }
3039
3040     Vector<FloatRect> rects;
3041     while (!rectComponents.isEmpty()) {
3042         double height = rectComponents.takeLast();
3043         double width = rectComponents.takeLast();
3044         double y = rectComponents.takeLast();
3045         double x = rectComponents.takeLast();
3046
3047         rects.append(FloatRect(x, y, width, height));
3048     }
3049
3050     rects.reverse();
3051
3052     Path path = PathUtilities::pathWithShrinkWrappedRects(rects, radius);
3053
3054     String pathString;
3055     buildStringFromPath(path, pathString);
3056
3057     return pathString;
3058 }
3059
3060
3061 String Internals::getCurrentMediaControlsStatusForElement(HTMLMediaElement* mediaElement)
3062 {
3063 #if !ENABLE(MEDIA_CONTROLS_SCRIPT)
3064     UNUSED_PARAM(mediaElement);
3065     return String();
3066 #else
3067     if (!mediaElement)
3068         return String();
3069
3070     return mediaElement->getCurrentMediaControlsStatus();
3071 #endif
3072 }
3073
3074 #if !PLATFORM(COCOA)
3075 String Internals::userVisibleString(const DOMURL*)
3076 {
3077     // Not implemented in WebCore.
3078     return String();
3079 }
3080 #endif
3081
3082 }