2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include "Internals.h"
30 #include "AXObjectCache.h"
31 #include "AnimationController.h"
32 #include "ApplicationCacheStorage.h"
33 #include "BackForwardController.h"
34 #include "CachedImage.h"
35 #include "CachedResourceLoader.h"
37 #include "ChromeClient.h"
38 #include "ClientRect.h"
39 #include "ClientRectList.h"
40 #include "ContentDistributor.h"
43 #include "DOMStringList.h"
44 #include "DOMWindow.h"
46 #include "DocumentMarker.h"
47 #include "DocumentMarkerController.h"
50 #include "EventHandler.h"
51 #include "ExceptionCode.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"
78 #include "InternalSettings.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"
89 #include "PageCache.h"
90 #include "PageOverlay.h"
91 #include "PathUtilities.h"
92 #include "PlatformMediaSessionManager.h"
93 #include "PrintContext.h"
94 #include "PseudoElement.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>
129 #if ENABLE(INPUT_TYPE_COLOR)
130 #include "ColorChooser.h"
133 #if ENABLE(BATTERY_STATUS)
134 #include "BatteryController.h"
137 #if ENABLE(PROXIMITY_EVENTS)
138 #include "DeviceProximityController.h"
141 #if ENABLE(MOUSE_CURSOR_SCALE)
142 #include <wtf/dtoa.h>
145 #if ENABLE(ENCRYPTED_MEDIA_V2)
150 #if ENABLE(VIDEO_TRACK)
151 #include "CaptionUserPreferences.h"
152 #include "PageGroup.h"
156 #include "HTMLMediaElement.h"
157 #include "TimeRanges.h"
160 #if ENABLE(SPEECH_SYNTHESIS)
161 #include "DOMWindowSpeechSynthesis.h"
162 #include "PlatformSpeechSynthesizerMock.h"
163 #include "SpeechSynthesis.h"
166 #if ENABLE(VIBRATION)
167 #include "Vibration.h"
170 #if ENABLE(MEDIA_STREAM)
171 #include "MockRealtimeMediaSourceCenter.h"
172 #include "RTCPeerConnection.h"
173 #include "RTCPeerConnectionHandlerMock.h"
174 #include "UserMediaClientMock.h"
177 #if ENABLE(MEDIA_SOURCE)
178 #include "MockMediaPlayerMediaSource.h"
182 #include "DictionaryLookup.h"
185 #if ENABLE(CONTENT_FILTERING)
186 #include "MockContentFilter.h"
189 #if ENABLE(WEB_AUDIO)
190 #include "AudioContext.h"
193 #if ENABLE(MEDIA_SESSION)
194 #include "MediaSession.h"
195 #include "MediaSessionManager.h"
198 using JSC::CodeBlock;
199 using JSC::FunctionExecutable;
200 using JSC::JSFunction;
202 using JSC::ScriptExecutable;
203 using JSC::StackVisitor;
205 using namespace Inspector;
209 using namespace HTMLNames;
211 class InspectorFrontendClientDummy : public InspectorFrontendClientLocal {
213 InspectorFrontendClientDummy(InspectorController*, Page*);
214 virtual ~InspectorFrontendClientDummy() { }
215 virtual void attachWindow(DockSide) override { }
216 virtual void detachWindow() override { }
218 virtual String localizedStringsURL() override { return String(); }
220 virtual void bringToFront() override { }
221 virtual void closeWindow() override { }
223 virtual void inspectedURLChanged(const String&) override { }
226 virtual void setAttachedWindowHeight(unsigned) override { }
227 virtual void setAttachedWindowWidth(unsigned) override { }
228 virtual void setToolbarHeight(unsigned) override { }
231 InspectorFrontendClientDummy::InspectorFrontendClientDummy(InspectorController* controller, Page* page)
232 : InspectorFrontendClientLocal(controller, page, std::make_unique<InspectorFrontendClientLocal::Settings>())
236 class InspectorFrontendChannelDummy : public InspectorFrontendChannel {
238 explicit InspectorFrontendChannelDummy(Page*);
239 virtual ~InspectorFrontendChannelDummy() { }
240 virtual bool sendMessageToFrontend(const String& message) override;
243 Page* m_frontendPage;
246 InspectorFrontendChannelDummy::InspectorFrontendChannelDummy(Page* page)
247 : m_frontendPage(page)
251 bool InspectorFrontendChannelDummy::sendMessageToFrontend(const String& message)
253 return InspectorClient::doDispatchMessageOnFrontendPage(m_frontendPage, message);
256 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
258 if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
259 result = DocumentMarker::AllMarkers();
260 else if (equalIgnoringCase(markerType, "Spelling"))
261 result = DocumentMarker::Spelling;
262 else if (equalIgnoringCase(markerType, "Grammar"))
263 result = DocumentMarker::Grammar;
264 else if (equalIgnoringCase(markerType, "TextMatch"))
265 result = DocumentMarker::TextMatch;
266 else if (equalIgnoringCase(markerType, "Replacement"))
267 result = DocumentMarker::Replacement;
268 else if (equalIgnoringCase(markerType, "CorrectionIndicator"))
269 result = DocumentMarker::CorrectionIndicator;
270 else if (equalIgnoringCase(markerType, "RejectedCorrection"))
271 result = DocumentMarker::RejectedCorrection;
272 else if (equalIgnoringCase(markerType, "Autocorrected"))
273 result = DocumentMarker::Autocorrected;
274 else if (equalIgnoringCase(markerType, "SpellCheckingExemption"))
275 result = DocumentMarker::SpellCheckingExemption;
276 else if (equalIgnoringCase(markerType, "DeletedAutocorrection"))
277 result = DocumentMarker::DeletedAutocorrection;
278 else if (equalIgnoringCase(markerType, "DictationAlternatives"))
279 result = DocumentMarker::DictationAlternatives;
280 #if ENABLE(TELEPHONE_NUMBER_DETECTION)
281 else if (equalIgnoringCase(markerType, "TelephoneNumber"))
282 result = DocumentMarker::TelephoneNumber;
290 const char* Internals::internalsId = "internals";
292 PassRefPtr<Internals> Internals::create(Document* document)
294 return adoptRef(new Internals(document));
297 Internals::~Internals()
301 void Internals::resetToConsistentState(Page* page)
305 page->setPageScaleFactor(1, IntPoint(0, 0));
306 page->setPagination(Pagination());
308 FrameView* mainFrameView = page->mainFrame().view();
310 mainFrameView->setHeaderHeight(0);
311 mainFrameView->setFooterHeight(0);
312 page->setTopContentInset(0);
313 mainFrameView->setUseFixedLayout(false);
314 mainFrameView->setFixedLayoutSize(IntSize());
317 TextRun::setAllowsRoundingHacks(false);
318 WebCore::overrideUserPreferredLanguages(Vector<String>());
319 WebCore::Settings::setUsesOverlayScrollbars(false);
320 page->inspectorController().setProfilerEnabled(false);
321 #if ENABLE(VIDEO_TRACK)
322 page->group().captionPreferences()->setCaptionsStyleSheetOverride(emptyString());
323 page->group().captionPreferences()->setTestingMode(false);
325 if (!page->mainFrame().editor().isContinuousSpellCheckingEnabled())
326 page->mainFrame().editor().toggleContinuousSpellChecking();
327 if (page->mainFrame().editor().isOverwriteModeEnabled())
328 page->mainFrame().editor().toggleOverwriteModeEnabled();
329 page->mainFrame().loader().clearTestingOverrides();
330 ApplicationCacheStorage::singleton().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
332 PlatformMediaSessionManager::sharedManager().resetRestrictions();
334 #if HAVE(ACCESSIBILITY)
335 AXObjectCache::setEnhancedUserInterfaceAccessibility(false);
336 AXObjectCache::disableAccessibility();
339 MockPageOverlayClient::singleton().uninstallAllOverlays();
341 #if ENABLE(CONTENT_FILTERING)
342 MockContentFilterSettings::reset();
346 Internals::Internals(Document* document)
347 : ContextDestructionObserver(document)
349 #if ENABLE(VIDEO_TRACK)
350 if (document && document->page())
351 document->page()->group().captionPreferences()->setTestingMode(true);
354 #if ENABLE(MEDIA_STREAM)
355 MockRealtimeMediaSourceCenter::registerMockRealtimeMediaSourceCenter();
356 enableMockRTCPeerConnectionHandler();
357 WebCore::provideUserMediaTo(document->page(), new UserMediaClientMock());
360 #if ENABLE(CONTENT_FILTERING)
361 MockContentFilter::ensureInstalled();
365 Document* Internals::contextDocument() const
367 return downcast<Document>(scriptExecutionContext());
370 Frame* Internals::frame() const
372 if (!contextDocument())
374 return contextDocument()->frame();
377 InternalSettings* Internals::settings() const
379 Document* document = contextDocument();
382 Page* page = document->page();
385 return InternalSettings::from(page);
388 unsigned Internals::workerThreadCount() const
390 return WorkerThread::workerThreadCount();
393 String Internals::address(Node* node)
395 return String::format("%p", node);
398 bool Internals::nodeNeedsStyleRecalc(Node* node, ExceptionCode& exception)
401 exception = INVALID_ACCESS_ERR;
405 return node->needsStyleRecalc();
408 String Internals::description(Deprecated::ScriptValue value)
410 return toString(value.jsValue());
413 bool Internals::isPreloaded(const String& url)
415 Document* document = contextDocument();
416 return document->cachedResourceLoader().isPreloaded(url);
419 bool Internals::isLoadingFromMemoryCache(const String& url)
421 if (!contextDocument() || !contextDocument()->page())
424 ResourceRequest request(contextDocument()->completeURL(url));
425 #if ENABLE(CACHE_PARTITIONING)
426 request.setDomainForCachePartition(contextDocument()->topOrigin()->domainForCachePartition());
428 CachedResource* resource = MemoryCache::singleton().resourceForRequest(request, contextDocument()->page()->sessionID());
429 return resource && resource->status() == CachedResource::Cached;
432 String Internals::xhrResponseSource(XMLHttpRequest* xhr)
436 if (xhr->resourceResponse().isNull())
437 return "Null response";
438 switch (xhr->resourceResponse().source()) {
439 case ResourceResponse::Source::Unknown:
441 case ResourceResponse::Source::Network:
443 case ResourceResponse::Source::DiskCache:
445 case ResourceResponse::Source::DiskCacheAfterValidation:
446 return "Disk cache after validation";
448 ASSERT_NOT_REACHED();
452 bool Internals::isSharingStyleSheetContents(Element* a, Element* b)
454 if (!is<HTMLLinkElement>(a) || !is<HTMLLinkElement>(b))
456 auto& aLink = downcast<HTMLLinkElement>(*a);
457 auto& bLink = downcast<HTMLLinkElement>(*b);
458 if (!aLink.sheet() || !bLink.sheet())
460 return &aLink.sheet()->contents() == &bLink.sheet()->contents();
463 bool Internals::isStyleSheetLoadingSubresources(Element* link)
465 if (!is<HTMLLinkElement>(link))
467 auto& linkElement = downcast<HTMLLinkElement>(*link);
468 return linkElement.sheet() && linkElement.sheet()->contents().isLoadingSubresources();
471 static ResourceRequestCachePolicy stringToResourceRequestCachePolicy(const String& policy)
473 if (policy == "UseProtocolCachePolicy")
474 return UseProtocolCachePolicy;
475 if (policy == "ReloadIgnoringCacheData")
476 return ReloadIgnoringCacheData;
477 if (policy == "ReturnCacheDataElseLoad")
478 return ReturnCacheDataElseLoad;
479 if (policy == "ReturnCacheDataDontLoad")
480 return ReturnCacheDataDontLoad;
481 ASSERT_NOT_REACHED();
482 return UseProtocolCachePolicy;
485 void Internals::setOverrideCachePolicy(const String& policy)
487 frame()->loader().setOverrideCachePolicyForTesting(stringToResourceRequestCachePolicy(policy));
490 static ResourceLoadPriority stringToResourceLoadPriority(const String& policy)
492 if (policy == "ResourceLoadPriorityVeryLow")
493 return ResourceLoadPriority::VeryLow;
494 if (policy == "ResourceLoadPriorityLow")
495 return ResourceLoadPriority::Low;
496 if (policy == "ResourceLoadPriorityMedium")
497 return ResourceLoadPriority::Medium;
498 if (policy == "ResourceLoadPriorityHigh")
499 return ResourceLoadPriority::High;
500 if (policy == "ResourceLoadPriorityVeryHigh")
501 return ResourceLoadPriority::VeryHigh;
502 ASSERT_NOT_REACHED();
503 return ResourceLoadPriority::Low;
506 void Internals::setOverrideResourceLoadPriority(const String& priority)
508 frame()->loader().setOverrideResourceLoadPriorityForTesting(stringToResourceLoadPriority(priority));
511 void Internals::clearMemoryCache()
513 MemoryCache::singleton().evictResources();
516 void Internals::pruneMemoryCacheToSize(unsigned size)
518 MemoryCache::singleton().pruneDeadResourcesToSize(size);
519 MemoryCache::singleton().pruneLiveResourcesToSize(size, true);
522 unsigned Internals::memoryCacheSize() const
524 return MemoryCache::singleton().size();
527 void Internals::clearPageCache()
529 PageCache::singleton().pruneToSizeNow(0, PruningReason::None);
532 unsigned Internals::pageCacheSize() const
534 return PageCache::singleton().pageCount();
537 Node* Internals::treeScopeRootNode(Node* node, ExceptionCode& ec)
540 ec = INVALID_ACCESS_ERR;
544 return &node->treeScope().rootNode();
547 Node* Internals::parentTreeScope(Node* node, ExceptionCode& ec)
550 ec = INVALID_ACCESS_ERR;
553 const TreeScope* parentTreeScope = node->treeScope().parentTreeScope();
554 return parentTreeScope ? &parentTreeScope->rootNode() : nullptr;
557 unsigned Internals::lastSpatialNavigationCandidateCount(ExceptionCode& ec) const
559 if (!contextDocument() || !contextDocument()->page()) {
560 ec = INVALID_ACCESS_ERR;
564 return contextDocument()->page()->lastSpatialNavigationCandidateCount();
567 unsigned Internals::numberOfActiveAnimations() const
569 return frame()->animation().numberOfActiveAnimations(frame()->document());
572 bool Internals::animationsAreSuspended(ExceptionCode& ec) const
574 Document* document = contextDocument();
575 if (!document || !document->frame()) {
576 ec = INVALID_ACCESS_ERR;
580 return document->frame()->animation().isSuspended();
583 void Internals::suspendAnimations(ExceptionCode& ec) const
585 Document* document = contextDocument();
586 if (!document || !document->frame()) {
587 ec = INVALID_ACCESS_ERR;
591 document->frame()->animation().suspendAnimations();
594 void Internals::resumeAnimations(ExceptionCode& ec) const
596 Document* document = contextDocument();
597 if (!document || !document->frame()) {
598 ec = INVALID_ACCESS_ERR;
602 document->frame()->animation().resumeAnimations();
605 bool Internals::pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element* element, ExceptionCode& ec)
607 if (!element || pauseTime < 0) {
608 ec = INVALID_ACCESS_ERR;
611 return frame()->animation().pauseAnimationAtTime(element->renderer(), AtomicString(animationName), pauseTime);
614 bool Internals::pauseAnimationAtTimeOnPseudoElement(const String& animationName, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec)
616 if (!element || pauseTime < 0) {
617 ec = INVALID_ACCESS_ERR;
621 if (pseudoId != "before" && pseudoId != "after") {
622 ec = INVALID_ACCESS_ERR;
626 PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement();
627 if (!pseudoElement) {
628 ec = INVALID_ACCESS_ERR;
632 return frame()->animation().pauseAnimationAtTime(pseudoElement->renderer(), AtomicString(animationName), pauseTime);
635 bool Internals::pauseTransitionAtTimeOnElement(const String& propertyName, double pauseTime, Element* element, ExceptionCode& ec)
637 if (!element || pauseTime < 0) {
638 ec = INVALID_ACCESS_ERR;
641 return frame()->animation().pauseTransitionAtTime(element->renderer(), propertyName, pauseTime);
644 bool Internals::pauseTransitionAtTimeOnPseudoElement(const String& property, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec)
646 if (!element || pauseTime < 0) {
647 ec = INVALID_ACCESS_ERR;
651 if (pseudoId != "before" && pseudoId != "after") {
652 ec = INVALID_ACCESS_ERR;
656 PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement();
657 if (!pseudoElement) {
658 ec = INVALID_ACCESS_ERR;
662 return frame()->animation().pauseTransitionAtTime(pseudoElement->renderer(), property, pauseTime);
666 bool Internals::attached(Node* node, ExceptionCode& ec)
669 ec = INVALID_ACCESS_ERR;
676 String Internals::elementRenderTreeAsText(Element* element, ExceptionCode& ec)
679 ec = INVALID_ACCESS_ERR;
683 element->document().updateStyleIfNeeded();
685 String representation = externalRepresentation(element);
686 if (representation.isEmpty()) {
687 ec = INVALID_ACCESS_ERR;
691 return representation;
694 bool Internals::hasPausedImageAnimations(Element* element, ExceptionCode& ec)
697 ec = INVALID_ACCESS_ERR;
700 return element->renderer() && element->renderer()->hasPausedImageAnimations();
703 PassRefPtr<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node* node, ExceptionCode& ec) const
706 ec = INVALID_ACCESS_ERR;
710 bool allowVisitedStyle = true;
711 return CSSComputedStyleDeclaration::create(node, allowVisitedStyle);
714 Node* Internals::ensureShadowRoot(Element* host, ExceptionCode& ec)
717 ec = INVALID_ACCESS_ERR;
721 if (ShadowRoot* shadowRoot = host->shadowRoot())
724 return host->createShadowRoot(ec).get();
727 Node* Internals::ensureUserAgentShadowRoot(Element* host, ExceptionCode& ec)
730 ec = INVALID_ACCESS_ERR;
733 return &host->ensureUserAgentShadowRoot();
736 Node* Internals::createShadowRoot(Element* host, ExceptionCode& ec)
739 ec = INVALID_ACCESS_ERR;
742 return host->createShadowRoot(ec).get();
745 Node* Internals::shadowRoot(Element* host, ExceptionCode& ec)
748 ec = INVALID_ACCESS_ERR;
751 return host->shadowRoot();
754 String Internals::shadowRootType(const Node* root, ExceptionCode& ec) const
756 if (!is<ShadowRoot>(root)) {
757 ec = INVALID_ACCESS_ERR;
761 switch (downcast<ShadowRoot>(*root).type()) {
762 case ShadowRoot::UserAgentShadowRoot:
763 return String("UserAgentShadowRoot");
765 ASSERT_NOT_REACHED();
766 return String("Unknown");
770 Element* Internals::includerFor(Node*, ExceptionCode& ec)
772 ec = INVALID_ACCESS_ERR;
776 String Internals::shadowPseudoId(Element* element, ExceptionCode& ec)
779 ec = INVALID_ACCESS_ERR;
783 return element->shadowPseudoId().string();
786 void Internals::setShadowPseudoId(Element* element, const String& id, ExceptionCode& ec)
789 ec = INVALID_ACCESS_ERR;
793 return element->setPseudo(id);
796 bool Internals::isTimerThrottled(int timeoutId, ExceptionCode& ec)
798 DOMTimer* timer = scriptExecutionContext()->findTimeout(timeoutId);
803 return timer->m_throttleState == DOMTimer::ShouldThrottle;
806 bool Internals::isRequestAnimationFrameThrottled() const
808 #if ENABLE(REQUEST_ANIMATION_FRAME)
809 auto* scriptedAnimationController = contextDocument()->scriptedAnimationController();
810 if (!scriptedAnimationController)
812 return scriptedAnimationController->isThrottled();
818 bool Internals::areTimersThrottled() const
820 return contextDocument()->isTimerThrottlingEnabled();
823 String Internals::visiblePlaceholder(Element* element)
825 if (is<HTMLTextFormControlElement>(element)) {
826 const HTMLTextFormControlElement& textFormControlElement = downcast<HTMLTextFormControlElement>(*element);
827 if (!textFormControlElement.isPlaceholderVisible())
829 if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
830 return placeholderElement->textContent();
836 #if ENABLE(INPUT_TYPE_COLOR)
837 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
839 if (!is<HTMLInputElement>(*element))
841 HTMLInputElement* inputElement = element->toInputElement();
844 inputElement->selectColorInColorChooser(Color(colorValue));
848 Vector<String> Internals::formControlStateOfPreviousHistoryItem(ExceptionCode& ec)
850 HistoryItem* mainItem = frame()->loader().history().previousItem();
852 ec = INVALID_ACCESS_ERR;
853 return Vector<String>();
855 String uniqueName = frame()->tree().uniqueName();
856 if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) {
857 ec = INVALID_ACCESS_ERR;
858 return Vector<String>();
860 return mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState();
863 void Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state, ExceptionCode& ec)
865 HistoryItem* mainItem = frame()->loader().history().previousItem();
867 ec = INVALID_ACCESS_ERR;
870 String uniqueName = frame()->tree().uniqueName();
871 if (mainItem->target() == uniqueName)
872 mainItem->setDocumentState(state);
873 else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
874 subItem->setDocumentState(state);
876 ec = INVALID_ACCESS_ERR;
879 #if ENABLE(SPEECH_SYNTHESIS)
880 void Internals::enableMockSpeechSynthesizer()
882 Document* document = contextDocument();
883 if (!document || !document->domWindow())
885 SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(document->domWindow());
889 synthesis->setPlatformSynthesizer(std::make_unique<PlatformSpeechSynthesizerMock>(synthesis));
893 #if ENABLE(MEDIA_STREAM)
894 void Internals::enableMockRTCPeerConnectionHandler()
896 RTCPeerConnectionHandler::create = RTCPeerConnectionHandlerMock::create;
900 Ref<ClientRect> Internals::absoluteCaretBounds(ExceptionCode& ec)
902 Document* document = contextDocument();
903 if (!document || !document->frame()) {
904 ec = INVALID_ACCESS_ERR;
905 return ClientRect::create();
908 return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
911 Ref<ClientRect> Internals::boundingBox(Element* element, ExceptionCode& ec)
914 ec = INVALID_ACCESS_ERR;
915 return ClientRect::create();
918 element->document().updateLayoutIgnorePendingStylesheets();
919 auto renderer = element->renderer();
921 return ClientRect::create();
922 return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
925 Ref<ClientRectList> Internals::inspectorHighlightRects(ExceptionCode& ec)
927 Document* document = contextDocument();
928 if (!document || !document->page()) {
929 ec = INVALID_ACCESS_ERR;
930 return ClientRectList::create();
934 document->page()->inspectorController().getHighlight(highlight, InspectorOverlay::CoordinateSystem::View);
935 return ClientRectList::create(highlight.quads);
938 String Internals::inspectorHighlightObject(ExceptionCode& ec)
940 Document* document = contextDocument();
941 if (!document || !document->page()) {
942 ec = INVALID_ACCESS_ERR;
946 return document->page()->inspectorController().buildObjectForHighlightedNodes()->toJSONString();
949 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionCode& ec)
952 ec = INVALID_ACCESS_ERR;
956 DocumentMarker::MarkerTypes markerTypes = 0;
957 if (!markerTypesFrom(markerType, markerTypes)) {
962 node->document().frame()->editor().updateEditorUINowIfScheduled();
964 return node->document().markers().markersFor(node, markerTypes).size();
967 RenderedDocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
969 node->document().updateLayoutIgnorePendingStylesheets();
971 ec = INVALID_ACCESS_ERR;
975 DocumentMarker::MarkerTypes markerTypes = 0;
976 if (!markerTypesFrom(markerType, markerTypes)) {
981 node->document().frame()->editor().updateEditorUINowIfScheduled();
983 Vector<RenderedDocumentMarker*> markers = node->document().markers().markersFor(node, markerTypes);
984 if (markers.size() <= index)
986 return markers[index];
989 PassRefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
991 RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
994 return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
997 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
999 RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
1002 return marker->description();
1005 void Internals::addTextMatchMarker(const Range* range, bool isActive)
1007 range->ownerDocument().updateLayoutIgnorePendingStylesheets();
1008 range->ownerDocument().markers().addTextMatchMarker(range, isActive);
1011 void Internals::setMarkedTextMatchesAreHighlighted(bool flag, ExceptionCode& ec)
1013 Document* document = contextDocument();
1014 if (!document || !document->frame()) {
1015 ec = INVALID_ACCESS_ERR;
1018 document->frame()->editor().setMarkedTextMatchesAreHighlighted(flag);
1021 void Internals::invalidateFontCache()
1023 FontCache::singleton().invalidate();
1026 void Internals::setScrollViewPosition(long x, long y, ExceptionCode& ec)
1028 Document* document = contextDocument();
1029 if (!document || !document->view()) {
1030 ec = INVALID_ACCESS_ERR;
1034 FrameView* frameView = document->view();
1035 bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
1036 bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
1038 frameView->setConstrainsScrollingToContentEdge(false);
1039 frameView->setScrollbarsSuppressed(false);
1040 frameView->setScrollOffsetFromInternals(IntPoint(x, y));
1041 frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
1042 frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
1045 void Internals::setViewBaseBackgroundColor(const String& colorValue, ExceptionCode& ec)
1047 Document* document = contextDocument();
1048 if (!document || !document->view()) {
1049 ec = INVALID_ACCESS_ERR;
1053 document->view()->setBaseBackgroundColor(Color(colorValue));
1056 void Internals::setPagination(const String& mode, int gap, int pageLength, ExceptionCode& ec)
1058 Document* document = contextDocument();
1059 if (!document || !document->page()) {
1060 ec = INVALID_ACCESS_ERR;
1063 Page* page = document->page();
1065 Pagination pagination;
1066 if (mode == "Unpaginated")
1067 pagination.mode = Pagination::Unpaginated;
1068 else if (mode == "LeftToRightPaginated")
1069 pagination.mode = Pagination::LeftToRightPaginated;
1070 else if (mode == "RightToLeftPaginated")
1071 pagination.mode = Pagination::RightToLeftPaginated;
1072 else if (mode == "TopToBottomPaginated")
1073 pagination.mode = Pagination::TopToBottomPaginated;
1074 else if (mode == "BottomToTopPaginated")
1075 pagination.mode = Pagination::BottomToTopPaginated;
1081 pagination.gap = gap;
1082 pagination.pageLength = pageLength;
1083 page->setPagination(pagination);
1086 String Internals::configurationForViewport(float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight, ExceptionCode& ec)
1088 Document* document = contextDocument();
1089 if (!document || !document->page()) {
1090 ec = INVALID_ACCESS_ERR;
1093 Page* page = document->page();
1095 const int defaultLayoutWidthForNonMobilePages = 980;
1097 ViewportArguments arguments = page->viewportArguments();
1098 ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
1099 restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
1100 restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
1102 return "viewport size " + String::number(attributes.layoutSize.width()) + "x" + String::number(attributes.layoutSize.height()) + " scale " + String::number(attributes.initialScale) + " with limits [" + String::number(attributes.minimumScale) + ", " + String::number(attributes.maximumScale) + "] and userScalable " + (attributes.userScalable ? "true" : "false");
1105 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionCode& ec)
1108 ec = INVALID_ACCESS_ERR;
1112 if (HTMLInputElement* inputElement = textField->toInputElement())
1113 return inputElement->lastChangeWasUserEdit();
1115 if (is<HTMLTextAreaElement>(*textField))
1116 return downcast<HTMLTextAreaElement>(*textField).lastChangeWasUserEdit();
1118 ec = INVALID_NODE_TYPE_ERR;
1122 bool Internals::elementShouldAutoComplete(Element* element, ExceptionCode& ec)
1125 ec = INVALID_ACCESS_ERR;
1129 if (HTMLInputElement* inputElement = element->toInputElement())
1130 return inputElement->shouldAutocomplete();
1132 ec = INVALID_NODE_TYPE_ERR;
1136 void Internals::setEditingValue(Element* element, const String& value, ExceptionCode& ec)
1139 ec = INVALID_ACCESS_ERR;
1143 HTMLInputElement* inputElement = element->toInputElement();
1144 if (!inputElement) {
1145 ec = INVALID_NODE_TYPE_ERR;
1149 inputElement->setEditingValue(value);
1152 void Internals::setAutofilled(Element* element, bool enabled, ExceptionCode& ec)
1154 HTMLInputElement* inputElement = element->toInputElement();
1155 if (!inputElement) {
1156 ec = INVALID_ACCESS_ERR;
1159 inputElement->setAutoFilled(enabled);
1162 void Internals::setShowAutoFillButton(Element* element, bool show, ExceptionCode& ec)
1164 HTMLInputElement* inputElement = element->toInputElement();
1165 if (!inputElement) {
1166 ec = INVALID_ACCESS_ERR;
1169 inputElement->setShowAutoFillButton(show);
1173 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionCode& ec)
1175 if (!element || !element->document().view()) {
1176 ec = INVALID_ACCESS_ERR;
1179 FrameView* frameView = element->document().view();
1180 frameView->scrollElementToRect(element, IntRect(x, y, w, h));
1183 void Internals::paintControlTints(ExceptionCode& ec)
1185 Document* document = contextDocument();
1186 if (!document || !document->view()) {
1187 ec = INVALID_ACCESS_ERR;
1191 FrameView* frameView = document->view();
1192 frameView->paintControlTints();
1195 PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionCode& ec)
1198 ec = INVALID_ACCESS_ERR;
1202 return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength);
1205 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1207 if (!scope || !range) {
1208 ec = INVALID_ACCESS_ERR;
1212 size_t location = 0;
1213 size_t unusedLength = 0;
1214 TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength);
1218 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1220 if (!scope || !range) {
1221 ec = INVALID_ACCESS_ERR;
1225 size_t unusedLocation = 0;
1227 TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length);
1231 String Internals::rangeAsText(const Range* range, ExceptionCode& ec)
1234 ec = INVALID_ACCESS_ERR;
1238 return range->text();
1241 PassRefPtr<Range> Internals::subrange(Range* range, int rangeLocation, int rangeLength, ExceptionCode& ec)
1244 ec = INVALID_ACCESS_ERR;
1248 return TextIterator::subrange(range, rangeLocation, rangeLength);
1251 RefPtr<Range> Internals::rangeForDictionaryLookupAtLocation(int x, int y, ExceptionCode& ec)
1254 Document* document = contextDocument();
1255 if (!document || !document->frame()) {
1256 ec = INVALID_ACCESS_ERR;
1260 document->updateLayoutIgnorePendingStylesheets();
1262 HitTestResult result = document->frame()->mainFrame().eventHandler().hitTestResultAtPoint(IntPoint(x, y));
1263 NSDictionary *options = nullptr;
1264 return rangeForDictionaryLookupAtHitTestResult(result, &options);
1268 ec = INVALID_ACCESS_ERR;
1273 void Internals::setDelegatesScrolling(bool enabled, ExceptionCode& ec)
1275 Document* document = contextDocument();
1276 // Delegate scrolling is valid only on mainframe's view.
1277 if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame()) {
1278 ec = INVALID_ACCESS_ERR;
1282 document->view()->setDelegatesScrolling(enabled);
1285 int Internals::lastSpellCheckRequestSequence(ExceptionCode& ec)
1287 Document* document = contextDocument();
1288 if (!document || !document->frame()) {
1289 ec = INVALID_ACCESS_ERR;
1293 return document->frame()->editor().spellChecker().lastRequestSequence();
1296 int Internals::lastSpellCheckProcessedSequence(ExceptionCode& ec)
1298 Document* document = contextDocument();
1299 if (!document || !document->frame()) {
1300 ec = INVALID_ACCESS_ERR;
1304 return document->frame()->editor().spellChecker().lastProcessedSequence();
1307 Vector<String> Internals::userPreferredLanguages() const
1309 return WebCore::userPreferredLanguages();
1312 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1314 WebCore::overrideUserPreferredLanguages(languages);
1317 Vector<String> Internals::userPreferredAudioCharacteristics() const
1319 Document* document = contextDocument();
1320 if (!document || !document->page())
1321 return Vector<String>();
1322 #if ENABLE(VIDEO_TRACK)
1323 return document->page()->group().captionPreferences()->preferredAudioCharacteristics();
1325 return Vector<String>();
1329 void Internals::setUserPreferredAudioCharacteristic(const String& characteristic)
1331 Document* document = contextDocument();
1332 if (!document || !document->page())
1334 #if ENABLE(VIDEO_TRACK)
1335 document->page()->group().captionPreferences()->setPreferredAudioCharacteristic(characteristic);
1337 UNUSED_PARAM(characteristic);
1341 unsigned Internals::wheelEventHandlerCount(ExceptionCode& ec)
1343 Document* document = contextDocument();
1345 ec = INVALID_ACCESS_ERR;
1349 return document->wheelEventHandlerCount();
1352 unsigned Internals::touchEventHandlerCount(ExceptionCode& ec)
1354 Document* document = contextDocument();
1356 ec = INVALID_ACCESS_ERR;
1360 return document->touchEventHandlerCount();
1363 // FIXME: Remove the document argument. It is almost always the same as
1364 // contextDocument(), with the exception of a few tests that pass a
1365 // different document, and could just make the call through another Internals
1366 // instance instead.
1367 PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
1368 unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionCode& ec) const
1370 if (!document || !document->frame() || !document->frame()->view()) {
1371 ec = INVALID_ACCESS_ERR;
1375 Frame* frame = document->frame();
1376 FrameView* frameView = document->view();
1377 RenderView* renderView = document->renderView();
1381 document->updateLayoutIgnorePendingStylesheets();
1383 float zoomFactor = frame->pageZoomFactor();
1384 LayoutPoint point(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY());
1386 HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
1388 hitType |= HitTestRequest::IgnoreClipping;
1389 if (!allowShadowContent)
1390 hitType |= HitTestRequest::DisallowShadowContent;
1391 if (allowChildFrameContent)
1392 hitType |= HitTestRequest::AllowChildFrameContent;
1394 HitTestRequest request(hitType);
1396 // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
1397 if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
1400 Vector<Ref<Node>> matches;
1402 // Need padding to trigger a rect based hit test, but we want to return a NodeList
1403 // so we special case this.
1404 if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
1405 HitTestResult result(point);
1406 renderView->hitTest(request, result);
1407 if (result.innerNode())
1408 matches.append(*result.innerNode()->deprecatedShadowAncestorNode());
1410 HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
1411 renderView->hitTest(request, result);
1413 const HitTestResult::NodeSet& nodeSet = result.rectBasedTestResult();
1414 matches.reserveInitialCapacity(nodeSet.size());
1415 for (auto& node : nodeSet)
1416 matches.uncheckedAppend(*node);
1419 return StaticNodeList::adopt(matches);
1422 class GetCallerCodeBlockFunctor {
1424 GetCallerCodeBlockFunctor()
1430 StackVisitor::Status operator()(StackVisitor& visitor)
1433 if (m_iterations < 2)
1434 return StackVisitor::Continue;
1436 m_codeBlock = visitor->codeBlock();
1437 return StackVisitor::Done;
1440 CodeBlock* codeBlock() const { return m_codeBlock; }
1444 CodeBlock* m_codeBlock;
1447 String Internals::parserMetaData(Deprecated::ScriptValue value)
1449 JSC::VM& vm = contextDocument()->vm();
1450 JSC::ExecState* exec = vm.topCallFrame;
1451 JSC::JSValue code = value.jsValue();
1452 ScriptExecutable* executable;
1454 if (!code || code.isNull() || code.isUndefined()) {
1455 GetCallerCodeBlockFunctor iter;
1456 exec->iterate(iter);
1457 CodeBlock* codeBlock = iter.codeBlock();
1458 executable = codeBlock->ownerExecutable();
1459 } else if (code.isFunction()) {
1460 JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec));
1461 executable = funcObj->jsExecutable();
1465 unsigned startLine = executable->firstLine();
1466 unsigned startColumn = executable->startColumn();
1467 unsigned endLine = executable->lastLine();
1468 unsigned endColumn = executable->endColumn();
1470 StringBuilder result;
1472 if (executable->isFunctionExecutable()) {
1473 FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable);
1474 String inferredName = funcExecutable->inferredName().string();
1475 result.appendLiteral("function \"");
1476 result.append(inferredName);
1478 } else if (executable->isEvalExecutable())
1479 result.appendLiteral("eval");
1481 ASSERT(executable->isProgramExecutable());
1482 result.appendLiteral("program");
1485 result.appendLiteral(" { ");
1486 result.appendNumber(startLine);
1488 result.appendNumber(startColumn);
1489 result.appendLiteral(" - ");
1490 result.appendNumber(endLine);
1492 result.appendNumber(endColumn);
1493 result.appendLiteral(" }");
1495 return result.toString();
1498 void Internals::setBatteryStatus(const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
1500 Document* document = contextDocument();
1501 if (!document || !document->page()) {
1502 ec = INVALID_ACCESS_ERR;
1506 #if ENABLE(BATTERY_STATUS)
1507 BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
1509 UNUSED_PARAM(eventType);
1510 UNUSED_PARAM(charging);
1511 UNUSED_PARAM(chargingTime);
1512 UNUSED_PARAM(dischargingTime);
1513 UNUSED_PARAM(level);
1517 void Internals::setDeviceProximity(const String& eventType, double value, double min, double max, ExceptionCode& ec)
1519 Document* document = contextDocument();
1520 if (!document || !document->page()) {
1521 ec = INVALID_ACCESS_ERR;
1525 #if ENABLE(PROXIMITY_EVENTS)
1526 DeviceProximityController::from(document->page())->didChangeDeviceProximity(value, min, max);
1528 UNUSED_PARAM(eventType);
1529 UNUSED_PARAM(value);
1535 void Internals::updateEditorUINowIfScheduled()
1537 if (Document* document = contextDocument()) {
1538 if (Frame* frame = document->frame())
1539 frame->editor().updateEditorUINowIfScheduled();
1543 bool Internals::hasSpellingMarker(int from, int length, ExceptionCode&)
1545 Document* document = contextDocument();
1546 if (!document || !document->frame())
1549 updateEditorUINowIfScheduled();
1551 return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1554 bool Internals::hasAutocorrectedMarker(int from, int length, ExceptionCode&)
1556 Document* document = contextDocument();
1557 if (!document || !document->frame())
1560 updateEditorUINowIfScheduled();
1562 return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
1565 void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionCode&)
1567 if (!contextDocument() || !contextDocument()->frame())
1570 if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
1571 contextDocument()->frame()->editor().toggleContinuousSpellChecking();
1574 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled, ExceptionCode&)
1576 if (!contextDocument() || !contextDocument()->frame())
1579 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1580 if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
1581 contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
1583 UNUSED_PARAM(enabled);
1587 void Internals::setAutomaticLinkDetectionEnabled(bool enabled, ExceptionCode&)
1589 if (!contextDocument() || !contextDocument()->frame())
1592 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1593 if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
1594 contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
1596 UNUSED_PARAM(enabled);
1600 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled, ExceptionCode&)
1602 if (!contextDocument() || !contextDocument()->frame())
1605 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1606 if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
1607 contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
1609 UNUSED_PARAM(enabled);
1613 void Internals::setAutomaticTextReplacementEnabled(bool enabled, ExceptionCode&)
1615 if (!contextDocument() || !contextDocument()->frame())
1618 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1619 if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
1620 contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
1622 UNUSED_PARAM(enabled);
1626 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled, ExceptionCode&)
1628 if (!contextDocument() || !contextDocument()->frame())
1631 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1632 if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
1633 contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
1635 UNUSED_PARAM(enabled);
1639 bool Internals::isOverwriteModeEnabled(ExceptionCode&)
1641 Document* document = contextDocument();
1642 if (!document || !document->frame())
1645 return document->frame()->editor().isOverwriteModeEnabled();
1648 void Internals::toggleOverwriteModeEnabled(ExceptionCode&)
1650 Document* document = contextDocument();
1651 if (!document || !document->frame())
1654 document->frame()->editor().toggleOverwriteModeEnabled();
1657 unsigned Internals::countMatchesForText(const String& text, unsigned findOptions, const String& markMatches, ExceptionCode&)
1659 Document* document = contextDocument();
1660 if (!document || !document->frame())
1663 bool mark = markMatches == "mark";
1664 return document->frame()->editor().countMatchesForText(text, nullptr, findOptions, 1000, mark, nullptr);
1667 const ProfilesArray& Internals::consoleProfiles() const
1669 return contextDocument()->page()->console().profiles();
1672 unsigned Internals::numberOfLiveNodes() const
1674 unsigned nodeCount = 0;
1675 for (auto* document : Document::allDocuments())
1676 nodeCount += document->referencingNodeCount();
1680 unsigned Internals::numberOfLiveDocuments() const
1682 return Document::allDocuments().size();
1685 Vector<String> Internals::consoleMessageArgumentCounts() const
1687 Document* document = contextDocument();
1688 if (!document || !document->page())
1689 return Vector<String>();
1691 InstrumentingAgents* instrumentingAgents = InspectorInstrumentation::instrumentingAgentsForPage(document->page());
1692 if (!instrumentingAgents)
1693 return Vector<String>();
1695 InspectorConsoleAgent* consoleAgent = instrumentingAgents->webConsoleAgent();
1697 return Vector<String>();
1699 Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
1700 Vector<String> result(counts.size());
1701 for (size_t i = 0; i < counts.size(); i++)
1702 result[i] = String::number(counts[i]);
1706 PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
1708 Page* page = contextDocument()->frame()->page();
1711 DOMWindow* window = page->mainFrame().document()->domWindow();
1714 m_frontendWindow = window->open(url, "", "", *window, *window);
1715 ASSERT(m_frontendWindow);
1717 Page* frontendPage = m_frontendWindow->document()->page();
1718 ASSERT(frontendPage);
1720 m_frontendClient = std::make_unique<InspectorFrontendClientDummy>(&page->inspectorController(), frontendPage);
1721 frontendPage->inspectorController().setInspectorFrontendClient(m_frontendClient.get());
1723 bool isAutomaticInspection = false;
1724 m_frontendChannel = std::make_unique<InspectorFrontendChannelDummy>(frontendPage);
1725 page->inspectorController().connectFrontend(m_frontendChannel.get(), isAutomaticInspection);
1727 return m_frontendWindow;
1730 void Internals::closeDummyInspectorFrontend()
1732 Page* page = contextDocument()->frame()->page();
1734 ASSERT(m_frontendWindow);
1736 page->inspectorController().disconnectFrontend(Inspector::DisconnectReason::InspectorDestroyed);
1738 m_frontendClient = nullptr;
1739 m_frontendChannel = nullptr;
1741 m_frontendWindow->close(m_frontendWindow->scriptExecutionContext());
1742 m_frontendWindow = nullptr;
1745 void Internals::setJavaScriptProfilingEnabled(bool enabled, ExceptionCode& ec)
1747 Page* page = contextDocument()->frame()->page();
1749 ec = INVALID_ACCESS_ERR;
1753 page->inspectorController().setProfilerEnabled(enabled);
1756 void Internals::setInspectorIsUnderTest(bool isUnderTest, ExceptionCode& ec)
1758 Page* page = contextDocument()->frame()->page();
1760 ec = INVALID_ACCESS_ERR;
1764 page->inspectorController().setIsUnderTest(isUnderTest);
1767 bool Internals::hasGrammarMarker(int from, int length, ExceptionCode&)
1769 Document* document = contextDocument();
1770 if (!document || !document->frame())
1773 return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1776 unsigned Internals::numberOfScrollableAreas(ExceptionCode&)
1778 Document* document = contextDocument();
1779 if (!document || !document->frame())
1783 Frame* frame = document->frame();
1784 if (frame->view()->scrollableAreas())
1785 count += frame->view()->scrollableAreas()->size();
1787 for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1788 if (child->view() && child->view()->scrollableAreas())
1789 count += child->view()->scrollableAreas()->size();
1795 bool Internals::isPageBoxVisible(int pageNumber, ExceptionCode& ec)
1797 Document* document = contextDocument();
1799 ec = INVALID_ACCESS_ERR;
1803 return document->isPageBoxVisible(pageNumber);
1806 // FIXME: Remove the document argument. It is almost always the same as
1807 // contextDocument(), with the exception of a few tests that pass a
1808 // different document, and could just make the call through another Internals
1809 // instance instead.
1810 String Internals::layerTreeAsText(Document* document, ExceptionCode& ec) const
1812 return layerTreeAsText(document, 0, ec);
1815 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionCode& ec) const
1817 if (!document || !document->frame()) {
1818 ec = INVALID_ACCESS_ERR;
1822 LayerTreeFlags layerTreeFlags = 0;
1823 if (flags & LAYER_TREE_INCLUDES_VISIBLE_RECTS)
1824 layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
1825 if (flags & LAYER_TREE_INCLUDES_TILE_CACHES)
1826 layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
1827 if (flags & LAYER_TREE_INCLUDES_REPAINT_RECTS)
1828 layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
1829 if (flags & LAYER_TREE_INCLUDES_PAINTING_PHASES)
1830 layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
1831 if (flags & LAYER_TREE_INCLUDES_CONTENT_LAYERS)
1832 layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
1834 return document->frame()->layerTreeAsText(layerTreeFlags);
1837 String Internals::repaintRectsAsText(ExceptionCode& ec) const
1839 Document* document = contextDocument();
1840 if (!document || !document->frame()) {
1841 ec = INVALID_ACCESS_ERR;
1845 return document->frame()->trackedRepaintRectsAsText();
1848 String Internals::scrollingStateTreeAsText(ExceptionCode& ec) const
1850 Document* document = contextDocument();
1851 if (!document || !document->frame()) {
1852 ec = INVALID_ACCESS_ERR;
1856 Page* page = document->page();
1860 return page->scrollingStateTreeAsText();
1863 String Internals::mainThreadScrollingReasons(ExceptionCode& ec) const
1865 Document* document = contextDocument();
1866 if (!document || !document->frame()) {
1867 ec = INVALID_ACCESS_ERR;
1871 Page* page = document->page();
1875 return page->synchronousScrollingReasonsAsText();
1878 RefPtr<ClientRectList> Internals::nonFastScrollableRects(ExceptionCode& ec) const
1880 Document* document = contextDocument();
1881 if (!document || !document->frame()) {
1882 ec = INVALID_ACCESS_ERR;
1886 Page* page = document->page();
1890 return page->nonFastScrollableRects();
1893 void Internals::garbageCollectDocumentResources(ExceptionCode& ec) const
1895 Document* document = contextDocument();
1897 ec = INVALID_ACCESS_ERR;
1900 document->cachedResourceLoader().garbageCollectDocumentResources();
1903 void Internals::allowRoundingHacks() const
1905 TextRun::setAllowsRoundingHacks(true);
1908 void Internals::insertAuthorCSS(const String& css, ExceptionCode& ec) const
1910 Document* document = contextDocument();
1912 ec = INVALID_ACCESS_ERR;
1916 auto parsedSheet = StyleSheetContents::create(*document);
1917 parsedSheet.get().setIsUserStyleSheet(false);
1918 parsedSheet.get().parseString(css);
1919 document->styleSheetCollection().addAuthorSheet(WTF::move(parsedSheet));
1922 void Internals::insertUserCSS(const String& css, ExceptionCode& ec) const
1924 Document* document = contextDocument();
1926 ec = INVALID_ACCESS_ERR;
1930 auto parsedSheet = StyleSheetContents::create(*document);
1931 parsedSheet.get().setIsUserStyleSheet(true);
1932 parsedSheet.get().parseString(css);
1933 document->styleSheetCollection().addUserSheet(WTF::move(parsedSheet));
1936 String Internals::counterValue(Element* element)
1941 return counterValueForElement(element);
1944 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1949 return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1952 Vector<String> Internals::shortcutIconURLs() const
1954 Vector<String> vector;
1959 auto string = frame()->loader().icon().url().string();
1960 if (!string.isNull())
1961 vector.append(string);
1965 int Internals::numberOfPages(float pageWidth, float pageHeight)
1970 return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
1973 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionCode& ec) const
1976 ec = INVALID_ACCESS_ERR;
1980 return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
1983 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionCode& ec) const
1986 ec = INVALID_ACCESS_ERR;
1990 return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
1993 void Internals::setPageScaleFactor(float scaleFactor, int x, int y, ExceptionCode& ec)
1995 Document* document = contextDocument();
1996 if (!document || !document->page()) {
1997 ec = INVALID_ACCESS_ERR;
2000 Page* page = document->page();
2001 page->setPageScaleFactor(scaleFactor, IntPoint(x, y));
2004 void Internals::setPageZoomFactor(float zoomFactor, ExceptionCode& ec)
2006 Document* document = contextDocument();
2007 if (!document || !document->frame()) {
2008 ec = INVALID_ACCESS_ERR;
2011 Frame* frame = document->frame();
2012 frame->setPageZoomFactor(zoomFactor);
2015 void Internals::setUseFixedLayout(bool useFixedLayout, ExceptionCode& ec)
2017 Document* document = contextDocument();
2018 if (!document || !document->view()) {
2019 ec = INVALID_ACCESS_ERR;
2022 FrameView* frameView = document->view();
2023 frameView->setUseFixedLayout(useFixedLayout);
2026 void Internals::setFixedLayoutSize(int width, int height, ExceptionCode& ec)
2028 Document* document = contextDocument();
2029 if (!document || !document->view()) {
2030 ec = INVALID_ACCESS_ERR;
2033 FrameView* frameView = document->view();
2034 frameView->setFixedLayoutSize(IntSize(width, height));
2037 void Internals::setHeaderHeight(float height)
2039 Document* document = contextDocument();
2040 if (!document || !document->view())
2043 FrameView* frameView = document->view();
2044 frameView->setHeaderHeight(height);
2047 void Internals::setFooterHeight(float height)
2049 Document* document = contextDocument();
2050 if (!document || !document->view())
2053 FrameView* frameView = document->view();
2054 frameView->setFooterHeight(height);
2057 void Internals::setTopContentInset(float contentInset)
2059 Document* document = contextDocument();
2063 Page* page = document->page();
2064 page->setTopContentInset(contentInset);
2067 #if ENABLE(FULLSCREEN_API)
2068 void Internals::webkitWillEnterFullScreenForElement(Element* element)
2070 Document* document = contextDocument();
2073 document->webkitWillEnterFullScreenForElement(element);
2076 void Internals::webkitDidEnterFullScreenForElement(Element* element)
2078 Document* document = contextDocument();
2081 document->webkitDidEnterFullScreenForElement(element);
2084 void Internals::webkitWillExitFullScreenForElement(Element* element)
2086 Document* document = contextDocument();
2089 document->webkitWillExitFullScreenForElement(element);
2092 void Internals::webkitDidExitFullScreenForElement(Element* element)
2094 Document* document = contextDocument();
2097 document->webkitDidExitFullScreenForElement(element);
2101 void Internals::setApplicationCacheOriginQuota(unsigned long long quota)
2103 Document* document = contextDocument();
2106 ApplicationCacheStorage::singleton().storeUpdatedQuotaForOrigin(document->securityOrigin(), quota);
2109 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
2111 SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
2114 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
2116 SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
2119 PassRefPtr<MallocStatistics> Internals::mallocStatistics() const
2121 return MallocStatistics::create();
2124 PassRefPtr<TypeConversions> Internals::typeConversions() const
2126 return TypeConversions::create();
2129 PassRefPtr<MemoryInfo> Internals::memoryInfo() const
2131 return MemoryInfo::create();
2134 Vector<String> Internals::getReferencedFilePaths() const
2136 frame()->loader().history().saveDocumentAndScrollState();
2137 return FormController::getReferencedFilePaths(frame()->loader().history().currentItem()->documentState());
2140 void Internals::startTrackingRepaints(ExceptionCode& ec)
2142 Document* document = contextDocument();
2143 if (!document || !document->view()) {
2144 ec = INVALID_ACCESS_ERR;
2148 FrameView* frameView = document->view();
2149 frameView->setTracksRepaints(true);
2152 void Internals::stopTrackingRepaints(ExceptionCode& ec)
2154 Document* document = contextDocument();
2155 if (!document || !document->view()) {
2156 ec = INVALID_ACCESS_ERR;
2160 FrameView* frameView = document->view();
2161 frameView->setTracksRepaints(false);
2164 void Internals::startTrackingLayerFlushes(ExceptionCode& ec)
2166 Document* document = contextDocument();
2167 if (!document || !document->renderView()) {
2168 ec = INVALID_ACCESS_ERR;
2172 document->renderView()->compositor().startTrackingLayerFlushes();
2175 unsigned long Internals::layerFlushCount(ExceptionCode& ec)
2177 Document* document = contextDocument();
2178 if (!document || !document->renderView()) {
2179 ec = INVALID_ACCESS_ERR;
2183 return document->renderView()->compositor().layerFlushCount();
2186 void Internals::startTrackingStyleRecalcs(ExceptionCode& ec)
2188 Document* document = contextDocument();
2190 ec = INVALID_ACCESS_ERR;
2193 document->startTrackingStyleRecalcs();
2196 unsigned long Internals::styleRecalcCount(ExceptionCode& ec)
2198 Document* document = contextDocument();
2200 ec = INVALID_ACCESS_ERR;
2204 return document->styleRecalcCount();
2207 void Internals::startTrackingCompositingUpdates(ExceptionCode& ec)
2209 Document* document = contextDocument();
2210 if (!document || !document->renderView()) {
2211 ec = INVALID_ACCESS_ERR;
2215 document->renderView()->compositor().startTrackingCompositingUpdates();
2218 unsigned long Internals::compositingUpdateCount(ExceptionCode& ec)
2220 Document* document = contextDocument();
2221 if (!document || !document->renderView()) {
2222 ec = INVALID_ACCESS_ERR;
2226 return document->renderView()->compositor().compositingUpdateCount();
2229 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(ExceptionCode& ec)
2231 updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(nullptr, ec);
2234 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionCode& ec)
2238 document = contextDocument();
2239 else if (is<Document>(*node))
2240 document = downcast<Document>(node);
2241 else if (is<HTMLIFrameElement>(*node))
2242 document = downcast<HTMLIFrameElement>(*node).contentDocument();
2248 document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
2251 unsigned Internals::layoutCount() const
2253 Document* document = contextDocument();
2254 if (!document || !document->view())
2256 return document->view()->layoutCount();
2260 static const char* cursorTypeToString(Cursor::Type cursorType)
2262 switch (cursorType) {
2263 case Cursor::Pointer: return "Pointer";
2264 case Cursor::Cross: return "Cross";
2265 case Cursor::Hand: return "Hand";
2266 case Cursor::IBeam: return "IBeam";
2267 case Cursor::Wait: return "Wait";
2268 case Cursor::Help: return "Help";
2269 case Cursor::EastResize: return "EastResize";
2270 case Cursor::NorthResize: return "NorthResize";
2271 case Cursor::NorthEastResize: return "NorthEastResize";
2272 case Cursor::NorthWestResize: return "NorthWestResize";
2273 case Cursor::SouthResize: return "SouthResize";
2274 case Cursor::SouthEastResize: return "SouthEastResize";
2275 case Cursor::SouthWestResize: return "SouthWestResize";
2276 case Cursor::WestResize: return "WestResize";
2277 case Cursor::NorthSouthResize: return "NorthSouthResize";
2278 case Cursor::EastWestResize: return "EastWestResize";
2279 case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
2280 case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
2281 case Cursor::ColumnResize: return "ColumnResize";
2282 case Cursor::RowResize: return "RowResize";
2283 case Cursor::MiddlePanning: return "MiddlePanning";
2284 case Cursor::EastPanning: return "EastPanning";
2285 case Cursor::NorthPanning: return "NorthPanning";
2286 case Cursor::NorthEastPanning: return "NorthEastPanning";
2287 case Cursor::NorthWestPanning: return "NorthWestPanning";
2288 case Cursor::SouthPanning: return "SouthPanning";
2289 case Cursor::SouthEastPanning: return "SouthEastPanning";
2290 case Cursor::SouthWestPanning: return "SouthWestPanning";
2291 case Cursor::WestPanning: return "WestPanning";
2292 case Cursor::Move: return "Move";
2293 case Cursor::VerticalText: return "VerticalText";
2294 case Cursor::Cell: return "Cell";
2295 case Cursor::ContextMenu: return "ContextMenu";
2296 case Cursor::Alias: return "Alias";
2297 case Cursor::Progress: return "Progress";
2298 case Cursor::NoDrop: return "NoDrop";
2299 case Cursor::Copy: return "Copy";
2300 case Cursor::None: return "None";
2301 case Cursor::NotAllowed: return "NotAllowed";
2302 case Cursor::ZoomIn: return "ZoomIn";
2303 case Cursor::ZoomOut: return "ZoomOut";
2304 case Cursor::Grab: return "Grab";
2305 case Cursor::Grabbing: return "Grabbing";
2306 case Cursor::Custom: return "Custom";
2309 ASSERT_NOT_REACHED();
2314 String Internals::getCurrentCursorInfo(ExceptionCode& ec)
2316 Document* document = contextDocument();
2317 if (!document || !document->frame()) {
2318 ec = INVALID_ACCESS_ERR;
2323 Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
2325 StringBuilder result;
2326 result.appendLiteral("type=");
2327 result.append(cursorTypeToString(cursor.type()));
2328 result.appendLiteral(" hotSpot=");
2329 result.appendNumber(cursor.hotSpot().x());
2331 result.appendNumber(cursor.hotSpot().y());
2332 if (cursor.image()) {
2333 FloatSize size = cursor.image()->size();
2334 result.appendLiteral(" image=");
2335 result.appendNumber(size.width());
2337 result.appendNumber(size.height());
2339 #if ENABLE(MOUSE_CURSOR_SCALE)
2340 if (cursor.imageScaleFactor() != 1) {
2341 result.appendLiteral(" scale=");
2342 NumberToStringBuffer buffer;
2343 result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
2346 return result.toString();
2348 return "FAIL: Cursor details not available on this platform.";
2352 PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
2354 Vector<uint8_t> bytes = value->data();
2355 return ArrayBuffer::create(bytes.data(), bytes.size());
2358 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
2360 Vector<uint8_t> bytes;
2361 bytes.append(static_cast<const uint8_t*>(buffer->data()), buffer->byteLength());
2362 return SerializedScriptValue::adopt(bytes);
2365 bool Internals::isFromCurrentWorld(Deprecated::ScriptValue value) const
2367 ASSERT(!value.hasNoValue());
2369 JSC::ExecState* exec = contextDocument()->vm().topCallFrame;
2370 if (!value.isObject() || &worldForDOMObject(value.jsValue().getObject()) == ¤tWorld(exec))
2375 void Internals::setUsesOverlayScrollbars(bool enabled)
2377 WebCore::Settings::setUsesOverlayScrollbars(enabled);
2380 void Internals::forceReload(bool endToEnd)
2382 frame()->loader().reload(endToEnd);
2385 #if ENABLE(ENCRYPTED_MEDIA_V2)
2386 void Internals::initializeMockCDM()
2388 CDM::registerCDMFactory([](CDM* cdm) { return std::make_unique<MockCDM>(cdm); },
2389 MockCDM::supportsKeySystem, MockCDM::supportsKeySystemAndMimeType);
2393 String Internals::markerTextForListItem(Element* element, ExceptionCode& ec)
2396 ec = INVALID_ACCESS_ERR;
2399 return WebCore::markerTextForListItem(element);
2402 String Internals::toolTipFromElement(Element* element, ExceptionCode& ec) const
2405 ec = INVALID_ACCESS_ERR;
2408 HitTestResult result;
2409 result.setInnerNode(element);
2411 return result.title(dir);
2414 String Internals::getImageSourceURL(Element* element, ExceptionCode& ec)
2417 ec = INVALID_ACCESS_ERR;
2420 return element->imageSourceURL();
2424 void Internals::simulateAudioInterruption(Node* node)
2427 HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2428 element->player()->simulateAudioInterruption();
2434 bool Internals::mediaElementHasCharacteristic(Node* node, const String& characteristic, ExceptionCode& ec)
2436 if (!is<HTMLMediaElement>(*node))
2439 HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2441 if (equalIgnoringCase(characteristic, "Audible"))
2442 return element->hasAudio();
2443 if (equalIgnoringCase(characteristic, "Visual"))
2444 return element->hasVideo();
2445 if (equalIgnoringCase(characteristic, "Legible"))
2446 return element->hasClosedCaptions();
2453 bool Internals::isSelectPopupVisible(Node* node)
2455 if (!is<HTMLSelectElement>(*node))
2458 HTMLSelectElement& select = downcast<HTMLSelectElement>(*node);
2460 auto* renderer = select.renderer();
2462 if (!is<RenderMenuList>(*renderer))
2466 return downcast<RenderMenuList>(*renderer).popupIsVisible();
2469 #endif // !PLATFORM(IOS)
2472 String Internals::captionsStyleSheetOverride(ExceptionCode& ec)
2474 Document* document = contextDocument();
2475 if (!document || !document->page()) {
2476 ec = INVALID_ACCESS_ERR;
2477 return emptyString();
2480 #if ENABLE(VIDEO_TRACK)
2481 return document->page()->group().captionPreferences()->captionsStyleSheetOverride();
2483 return emptyString();
2487 void Internals::setCaptionsStyleSheetOverride(const String& override, ExceptionCode& ec)
2489 Document* document = contextDocument();
2490 if (!document || !document->page()) {
2491 ec = INVALID_ACCESS_ERR;
2495 #if ENABLE(VIDEO_TRACK)
2496 document->page()->group().captionPreferences()->setCaptionsStyleSheetOverride(override);
2498 UNUSED_PARAM(override);
2502 void Internals::setPrimaryAudioTrackLanguageOverride(const String& language, ExceptionCode& ec)
2504 Document* document = contextDocument();
2505 if (!document || !document->page()) {
2506 ec = INVALID_ACCESS_ERR;
2510 #if ENABLE(VIDEO_TRACK)
2511 document->page()->group().captionPreferences()->setPrimaryAudioTrackLanguageOverride(language);
2513 UNUSED_PARAM(language);
2517 void Internals::setCaptionDisplayMode(const String& mode, ExceptionCode& ec)
2519 Document* document = contextDocument();
2520 if (!document || !document->page()) {
2521 ec = INVALID_ACCESS_ERR;
2525 #if ENABLE(VIDEO_TRACK)
2526 CaptionUserPreferences* captionPreferences = document->page()->group().captionPreferences();
2528 if (equalIgnoringCase(mode, "Automatic"))
2529 captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::Automatic);
2530 else if (equalIgnoringCase(mode, "ForcedOnly"))
2531 captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
2532 else if (equalIgnoringCase(mode, "AlwaysOn"))
2533 captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn);
2542 PassRefPtr<TimeRanges> Internals::createTimeRanges(Float32Array* startTimes, Float32Array* endTimes)
2544 ASSERT(startTimes && endTimes);
2545 ASSERT(startTimes->length() == endTimes->length());
2546 RefPtr<TimeRanges> ranges = TimeRanges::create();
2548 unsigned count = std::min(startTimes->length(), endTimes->length());
2549 for (unsigned i = 0; i < count; ++i)
2550 ranges->add(startTimes->item(i), endTimes->item(i));
2554 double Internals::closestTimeToTimeRanges(double time, TimeRanges* ranges)
2556 return ranges->nearest(time);
2560 Ref<ClientRect> Internals::selectionBounds(ExceptionCode& ec)
2562 Document* document = contextDocument();
2563 if (!document || !document->frame()) {
2564 ec = INVALID_ACCESS_ERR;
2565 return ClientRect::create();
2568 return ClientRect::create(document->frame()->selection().selectionBounds());
2571 #if ENABLE(VIBRATION)
2572 bool Internals::isVibrating()
2574 Page* page = contextDocument()->page();
2577 return Vibration::from(page)->isVibrating();
2581 bool Internals::isPluginUnavailabilityIndicatorObscured(Element* element, ExceptionCode& ec)
2584 ec = INVALID_ACCESS_ERR;
2588 auto* renderer = element->renderer();
2589 if (!is<RenderEmbeddedObject>(renderer)) {
2590 ec = INVALID_ACCESS_ERR;
2594 return downcast<RenderEmbeddedObject>(*renderer).isReplacementObscured();
2597 bool Internals::isPluginSnapshotted(Element* element, ExceptionCode& ec)
2600 ec = INVALID_ACCESS_ERR;
2603 HTMLPlugInElement* pluginElement = downcast<HTMLPlugInElement>(element);
2604 return pluginElement->displayState() <= HTMLPlugInElement::DisplayingSnapshot;
2607 #if ENABLE(MEDIA_SOURCE)
2608 void Internals::initializeMockMediaSource()
2610 #if USE(AVFOUNDATION)
2611 WebCore::Settings::setAVFoundationEnabled(false);
2613 MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
2616 Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer* buffer, const AtomicString& trackID)
2619 return Vector<String>();
2621 return buffer->bufferedSamplesForTrackID(trackID);
2626 void Internals::beginMediaSessionInterruption()
2628 PlatformMediaSessionManager::sharedManager().beginInterruption(PlatformMediaSession::SystemInterruption);
2631 void Internals::endMediaSessionInterruption(const String& flagsString)
2633 PlatformMediaSession::EndInterruptionFlags flags = PlatformMediaSession::NoFlags;
2635 if (equalIgnoringCase(flagsString, "MayResumePlaying"))
2636 flags = PlatformMediaSession::MayResumePlaying;
2638 PlatformMediaSessionManager::sharedManager().endInterruption(flags);
2641 void Internals::applicationWillEnterForeground() const
2643 PlatformMediaSessionManager::sharedManager().applicationWillEnterForeground();
2646 void Internals::applicationWillEnterBackground() const
2648 PlatformMediaSessionManager::sharedManager().applicationWillEnterBackground();
2651 void Internals::setMediaSessionRestrictions(const String& mediaTypeString, const String& restrictionsString, ExceptionCode& ec)
2653 PlatformMediaSession::MediaType mediaType = PlatformMediaSession::None;
2654 if (equalIgnoringCase(mediaTypeString, "Video"))
2655 mediaType = PlatformMediaSession::Video;
2656 else if (equalIgnoringCase(mediaTypeString, "Audio"))
2657 mediaType = PlatformMediaSession::Audio;
2658 else if (equalIgnoringCase(mediaTypeString, "WebAudio"))
2659 mediaType = PlatformMediaSession::WebAudio;
2661 ec = INVALID_ACCESS_ERR;
2665 PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType);
2666 PlatformMediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions);
2668 restrictions = PlatformMediaSessionManager::NoRestrictions;
2670 Vector<String> restrictionsArray;
2671 restrictionsString.split(',', false, restrictionsArray);
2672 for (auto& restrictionString : restrictionsArray) {
2673 if (equalIgnoringCase(restrictionString, "ConcurrentPlaybackNotPermitted"))
2674 restrictions |= PlatformMediaSessionManager::ConcurrentPlaybackNotPermitted;
2675 if (equalIgnoringCase(restrictionString, "InlineVideoPlaybackRestricted"))
2676 restrictions |= PlatformMediaSessionManager::InlineVideoPlaybackRestricted;
2677 if (equalIgnoringCase(restrictionString, "MetadataPreloadingNotPermitted"))
2678 restrictions |= PlatformMediaSessionManager::MetadataPreloadingNotPermitted;
2679 if (equalIgnoringCase(restrictionString, "AutoPreloadingNotPermitted"))
2680 restrictions |= PlatformMediaSessionManager::AutoPreloadingNotPermitted;
2681 if (equalIgnoringCase(restrictionString, "BackgroundProcessPlaybackRestricted"))
2682 restrictions |= PlatformMediaSessionManager::BackgroundProcessPlaybackRestricted;
2683 if (equalIgnoringCase(restrictionString, "BackgroundTabPlaybackRestricted"))
2684 restrictions |= PlatformMediaSessionManager::BackgroundTabPlaybackRestricted;
2685 if (equalIgnoringCase(restrictionString, "InterruptedPlaybackNotPermitted"))
2686 restrictions |= PlatformMediaSessionManager::InterruptedPlaybackNotPermitted;
2688 PlatformMediaSessionManager::sharedManager().addRestriction(mediaType, restrictions);
2691 void Internals::setMediaElementRestrictions(HTMLMediaElement* element, const String& restrictionsString, ExceptionCode& ec)
2694 ec = INVALID_ACCESS_ERR;
2698 MediaElementSession::BehaviorRestrictions restrictions = element->mediaSession().behaviorRestrictions();
2699 element->mediaSession().removeBehaviorRestriction(restrictions);
2701 restrictions = MediaElementSession::NoRestrictions;
2703 Vector<String> restrictionsArray;
2704 restrictionsString.split(',', false, restrictionsArray);
2705 for (auto& restrictionString : restrictionsArray) {
2706 if (equalIgnoringCase(restrictionString, "NoRestrictions"))
2707 restrictions |= MediaElementSession::NoRestrictions;
2708 if (equalIgnoringCase(restrictionString, "RequireUserGestureForLoad"))
2709 restrictions |= MediaElementSession::RequireUserGestureForLoad;
2710 if (equalIgnoringCase(restrictionString, "RequireUserGestureForRateChange"))
2711 restrictions |= MediaElementSession::RequireUserGestureForRateChange;
2712 if (equalIgnoringCase(restrictionString, "RequireUserGestureForFullscreen"))
2713 restrictions |= MediaElementSession::RequireUserGestureForFullscreen;
2714 if (equalIgnoringCase(restrictionString, "RequirePageConsentToLoadMedia"))
2715 restrictions |= MediaElementSession::RequirePageConsentToLoadMedia;
2716 if (equalIgnoringCase(restrictionString, "RequirePageConsentToResumeMedia"))
2717 restrictions |= MediaElementSession::RequirePageConsentToResumeMedia;
2718 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
2719 if (equalIgnoringCase(restrictionString, "RequireUserGestureToShowPlaybackTargetPicker"))
2720 restrictions |= MediaElementSession::RequireUserGestureToShowPlaybackTargetPicker;
2721 if (equalIgnoringCase(restrictionString, "WirelessVideoPlaybackDisabled"))
2722 restrictions |= MediaElementSession::WirelessVideoPlaybackDisabled;
2724 if (equalIgnoringCase(restrictionString, "RequireUserGestureForAudioRateChange"))
2725 restrictions |= MediaElementSession::RequireUserGestureForAudioRateChange;
2727 element->mediaSession().addBehaviorRestriction(restrictions);
2730 void Internals::postRemoteControlCommand(const String& commandString, ExceptionCode& ec)
2732 PlatformMediaSession::RemoteControlCommandType command;
2734 if (equalIgnoringCase(commandString, "Play"))
2735 command = PlatformMediaSession::PlayCommand;
2736 else if (equalIgnoringCase(commandString, "Pause"))
2737 command = PlatformMediaSession::PauseCommand;
2738 else if (equalIgnoringCase(commandString, "Stop"))
2739 command = PlatformMediaSession::StopCommand;
2740 else if (equalIgnoringCase(commandString, "TogglePlayPause"))
2741 command = PlatformMediaSession::TogglePlayPauseCommand;
2742 else if (equalIgnoringCase(commandString, "BeginSeekingBackward"))
2743 command = PlatformMediaSession::BeginSeekingBackwardCommand;
2744 else if (equalIgnoringCase(commandString, "EndSeekingBackward"))
2745 command = PlatformMediaSession::EndSeekingBackwardCommand;
2746 else if (equalIgnoringCase(commandString, "BeginSeekingForward"))
2747 command = PlatformMediaSession::BeginSeekingForwardCommand;
2748 else if (equalIgnoringCase(commandString, "EndSeekingForward"))
2749 command = PlatformMediaSession::EndSeekingForwardCommand;
2751 ec = INVALID_ACCESS_ERR;
2755 PlatformMediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command);
2758 bool Internals::elementIsBlockingDisplaySleep(Element* element) const
2760 HTMLMediaElement* mediaElement = downcast<HTMLMediaElement>(element);
2761 return mediaElement ? mediaElement->isDisablingSleep() : false;
2764 #endif // ENABLE(VIDEO)
2766 #if ENABLE(MEDIA_SESSION)
2767 static MediaSessionInterruptingCategory interruptingCategoryFromString(const String& interruptingCategoryString)
2769 if (interruptingCategoryString == "content")
2770 return MediaSessionInterruptingCategory::Content;
2771 if (interruptingCategoryString == "transient")
2772 return MediaSessionInterruptingCategory::Transient;
2773 if (interruptingCategoryString == "transient-solo")
2774 return MediaSessionInterruptingCategory::TransientSolo;
2775 ASSERT_NOT_REACHED();
2778 void Internals::sendMediaSessionStartOfInterruptionNotification(const String& interruptingCategoryString)
2780 MediaSessionManager::singleton().didReceiveStartOfInterruptionNotification(interruptingCategoryFromString(interruptingCategoryString));
2783 void Internals::sendMediaSessionEndOfInterruptionNotification(const String& interruptingCategoryString)
2785 MediaSessionManager::singleton().didReceiveEndOfInterruptionNotification(interruptingCategoryFromString(interruptingCategoryString));
2788 String Internals::mediaSessionCurrentState(MediaSession* session) const
2790 switch (session->currentState()) {
2791 case MediaSession::State::Active:
2793 case MediaSession::State::Interrupted:
2794 return "interrupted";
2795 case MediaSession::State::Idle:
2799 #endif // ENABLE(MEDIA_SESSION)
2801 #if ENABLE(WEB_AUDIO)
2802 void Internals::setAudioContextRestrictions(AudioContext* context, const String &restrictionsString, ExceptionCode &ec)
2805 ec = INVALID_ACCESS_ERR;
2809 AudioContext::BehaviorRestrictions restrictions = context->behaviorRestrictions();
2810 context->removeBehaviorRestriction(restrictions);
2812 restrictions = MediaElementSession::NoRestrictions;
2814 Vector<String> restrictionsArray;
2815 restrictionsString.split(',', false, restrictionsArray);
2816 for (auto& restrictionString : restrictionsArray) {
2817 if (equalIgnoringCase(restrictionString, "NoRestrictions"))
2818 restrictions |= AudioContext::NoRestrictions;
2819 if (equalIgnoringCase(restrictionString, "RequireUserGestureForAudioStart"))
2820 restrictions |= AudioContext::RequireUserGestureForAudioStartRestriction;
2821 if (equalIgnoringCase(restrictionString, "RequirePageConsentForAudioStart"))
2822 restrictions |= AudioContext::RequirePageConsentForAudioStartRestriction;
2824 context->addBehaviorRestriction(restrictions);
2828 void Internals::simulateSystemSleep() const
2831 PlatformMediaSessionManager::sharedManager().systemWillSleep();
2835 void Internals::simulateSystemWake() const
2838 PlatformMediaSessionManager::sharedManager().systemDidWake();
2843 void Internals::installMockPageOverlay(const String& overlayType, ExceptionCode& ec)
2845 Document* document = contextDocument();
2846 if (!document || !document->frame()) {
2847 ec = INVALID_ACCESS_ERR;
2851 MockPageOverlayClient::singleton().installOverlay(document->frame()->mainFrame(), overlayType == "view" ? PageOverlay::OverlayType::View : PageOverlay::OverlayType::Document);
2854 String Internals::pageOverlayLayerTreeAsText(ExceptionCode& ec) const
2856 Document* document = contextDocument();
2857 if (!document || !document->frame()) {
2858 ec = INVALID_ACCESS_ERR;
2862 document->updateLayout();
2864 return MockPageOverlayClient::singleton().layerTreeAsText(document->frame()->mainFrame());
2867 void Internals::setPageMuted(bool muted)
2869 Document* document = contextDocument();
2873 if (Page* page = document->page())
2874 page->setMuted(muted);
2877 bool Internals::isPagePlayingAudio()
2879 Document* document = contextDocument();
2880 if (!document || !document->page())
2883 return !!(document->page()->mediaState() & MediaProducer::IsPlayingAudio);
2886 RefPtr<File> Internals::createFile(const String& path)
2888 Document* document = contextDocument();
2892 URL url = document->completeURL(path);
2893 if (!url.isLocalFile())
2896 return File::create(url.fileSystemPath());
2899 void Internals::queueMicroTask(int testNumber)
2901 if (contextDocument())
2902 MicroTaskQueue::singleton().queueMicroTask(std::make_unique<MicroTaskTest>(contextDocument()->createWeakPtr(), testNumber));
2905 #if ENABLE(CONTENT_FILTERING)
2906 MockContentFilterSettings& Internals::mockContentFilterSettings()
2908 return MockContentFilterSettings::singleton();
2912 #if ENABLE(CSS_SCROLL_SNAP)
2913 static void appendOffsets(StringBuilder& builder, const Vector<LayoutUnit>& snapOffsets)
2915 bool justStarting = true;
2917 builder.append("{ ");
2918 for (auto& coordinate : snapOffsets) {
2920 builder.append(", ");
2922 justStarting = false;
2924 builder.append(String::number(coordinate.toUnsigned()));
2926 builder.append(" }");
2929 String Internals::scrollSnapOffsets(Element* element, ExceptionCode& ec)
2932 ec = INVALID_ACCESS_ERR;
2936 if (!element->renderBox())
2939 RenderBox& box = *element->renderBox();
2940 ScrollableArea* scrollableArea;
2943 FrameView* frameView = box.frame().mainFrame().view();
2944 if (!frameView || !frameView->isScrollable()) {
2945 ec = INVALID_ACCESS_ERR;
2948 scrollableArea = frameView;
2951 if (!box.canBeScrolledAndHasScrollableArea()) {
2952 ec = INVALID_ACCESS_ERR;
2955 scrollableArea = box.layer();
2958 if (!scrollableArea)
2961 StringBuilder result;
2963 if (scrollableArea->horizontalSnapOffsets()) {
2964 result.append("horizontal = ");
2965 appendOffsets(result, *scrollableArea->horizontalSnapOffsets());
2968 if (scrollableArea->verticalSnapOffsets()) {
2969 if (result.length())
2970 result.append(", ");
2972 result.append("vertical = ");
2973 appendOffsets(result, *scrollableArea->verticalSnapOffsets());
2976 return result.toString();
2980 bool Internals::testPreloaderSettingViewport()
2982 return testPreloadScannerViewportSupport(contextDocument());
2985 String Internals::pathStringWithShrinkWrappedRects(Vector<double> rectComponents, double radius, ExceptionCode& ec)
2987 if (rectComponents.size() % 4) {
2988 ec = INVALID_ACCESS_ERR;
2992 Vector<FloatRect> rects;
2993 while (!rectComponents.isEmpty()) {
2994 double height = rectComponents.takeLast();
2995 double width = rectComponents.takeLast();
2996 double y = rectComponents.takeLast();
2997 double x = rectComponents.takeLast();
2999 rects.append(FloatRect(x, y, width, height));
3004 Path path = PathUtilities::pathWithShrinkWrappedRects(rects, radius);
3007 buildStringFromPath(path, pathString);