fc36d8f99136192e3b5fc0ea2b432ff804d7e87b
[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 "CachedResourceLoader.h"
35 #include "Chrome.h"
36 #include "ChromeClient.h"
37 #include "ClientRect.h"
38 #include "ClientRectList.h"
39 #include "ContentDistributor.h"
40 #include "Cursor.h"
41 #include "DOMStringList.h"
42 #include "DOMWindow.h"
43 #include "Document.h"
44 #include "DocumentMarker.h"
45 #include "DocumentMarkerController.h"
46 #include "Editor.h"
47 #include "Element.h"
48 #include "EventHandler.h"
49 #include "ExceptionCode.h"
50 #include "FontCache.h"
51 #include "FormController.h"
52 #include "FrameLoader.h"
53 #include "FrameView.h"
54 #include "HTMLIFrameElement.h"
55 #include "HTMLInputElement.h"
56 #include "HTMLNames.h"
57 #include "HTMLPlugInElement.h"
58 #include "HTMLSelectElement.h"
59 #include "HTMLTextAreaElement.h"
60 #include "HistoryController.h"
61 #include "HistoryItem.h"
62 #include "InspectorClient.h"
63 #include "InspectorController.h"
64 #include "InspectorForwarding.h"
65 #include "InspectorFrontendClientLocal.h"
66 #include "InspectorInstrumentation.h"
67 #include "InspectorOverlay.h"
68 #include "InstrumentingAgents.h"
69 #include "IntRect.h"
70 #include "InternalSettings.h"
71 #include "Language.h"
72 #include "MainFrame.h"
73 #include "MallocStatistics.h"
74 #include "MediaPlayer.h"
75 #include "MediaSessionManager.h"
76 #include "MemoryCache.h"
77 #include "MemoryInfo.h"
78 #include "MockPageOverlayClient.h"
79 #include "Page.h"
80 #include "PageOverlay.h"
81 #include "PrintContext.h"
82 #include "PseudoElement.h"
83 #include "Range.h"
84 #include "RenderEmbeddedObject.h"
85 #include "RenderMenuList.h"
86 #include "RenderTreeAsText.h"
87 #include "RenderView.h"
88 #include "RenderedDocumentMarker.h"
89 #include "RuntimeEnabledFeatures.h"
90 #include "SchemeRegistry.h"
91 #include "ScrollingCoordinator.h"
92 #include "SerializedScriptValue.h"
93 #include "Settings.h"
94 #include "ShadowRoot.h"
95 #include "SourceBuffer.h"
96 #include "SpellChecker.h"
97 #include "StaticNodeList.h"
98 #include "StyleSheetContents.h"
99 #include "TextIterator.h"
100 #include "TreeScope.h"
101 #include "TypeConversions.h"
102 #include "ViewportArguments.h"
103 #include "WebConsoleAgent.h"
104 #include "WorkerThread.h"
105 #include <bytecode/CodeBlock.h>
106 #include <inspector/InspectorAgentBase.h>
107 #include <inspector/InspectorValues.h>
108 #include <runtime/JSCInlines.h>
109 #include <runtime/JSCJSValue.h>
110 #include <wtf/text/CString.h>
111 #include <wtf/text/StringBuffer.h>
112
113 #if ENABLE(INPUT_TYPE_COLOR)
114 #include "ColorChooser.h"
115 #endif
116
117 #if ENABLE(BATTERY_STATUS)
118 #include "BatteryController.h"
119 #endif
120
121 #if ENABLE(PROXIMITY_EVENTS)
122 #include "DeviceProximityController.h"
123 #endif
124
125 #if ENABLE(MOUSE_CURSOR_SCALE)
126 #include <wtf/dtoa.h>
127 #endif
128
129 #if ENABLE(ENCRYPTED_MEDIA_V2)
130 #include "CDM.h"
131 #include "MockCDM.h"
132 #endif
133
134 #if ENABLE(VIDEO_TRACK)
135 #include "CaptionUserPreferences.h"
136 #include "PageGroup.h"
137 #endif
138
139 #if ENABLE(VIDEO)
140 #include "HTMLMediaElement.h"
141 #include "TimeRanges.h"
142 #endif
143
144 #if ENABLE(SPEECH_SYNTHESIS)
145 #include "DOMWindowSpeechSynthesis.h"
146 #include "PlatformSpeechSynthesizerMock.h"
147 #include "SpeechSynthesis.h"
148 #endif
149
150 #if ENABLE(VIBRATION)
151 #include "Vibration.h"
152 #endif
153
154 #if ENABLE(MEDIA_STREAM)
155 #include "MockMediaStreamCenter.h"
156 #include "RTCPeerConnection.h"
157 #include "RTCPeerConnectionHandlerMock.h"
158 #include "UserMediaClientMock.h"
159 #endif
160
161 #if ENABLE(MEDIA_SOURCE)
162 #include "MockMediaPlayerMediaSource.h"
163 #endif
164
165 using JSC::CodeBlock;
166 using JSC::FunctionExecutable;
167 using JSC::JSFunction;
168 using JSC::JSValue;
169 using JSC::ScriptExecutable;
170 using JSC::StackVisitor;
171
172 using namespace Inspector;
173
174 namespace WebCore {
175
176 using namespace HTMLNames;
177
178 #if ENABLE(INSPECTOR)
179 class InspectorFrontendClientDummy : public InspectorFrontendClientLocal {
180 public:
181     InspectorFrontendClientDummy(InspectorController*, Page*);
182     virtual ~InspectorFrontendClientDummy() { }
183     virtual void attachWindow(DockSide) override { }
184     virtual void detachWindow() override { }
185
186     virtual String localizedStringsURL() override { return String(); }
187
188     virtual void bringToFront() override { }
189     virtual void closeWindow() override { }
190
191     virtual void inspectedURLChanged(const String&) override { }
192
193 protected:
194     virtual void setAttachedWindowHeight(unsigned) override { }
195     virtual void setAttachedWindowWidth(unsigned) override { }
196     virtual void setToolbarHeight(unsigned) override { }
197 };
198
199 InspectorFrontendClientDummy::InspectorFrontendClientDummy(InspectorController* controller, Page* page)
200     : InspectorFrontendClientLocal(controller, page, std::make_unique<InspectorFrontendClientLocal::Settings>())
201 {
202 }
203
204 class InspectorFrontendChannelDummy : public InspectorFrontendChannel {
205 public:
206     explicit InspectorFrontendChannelDummy(Page*);
207     virtual ~InspectorFrontendChannelDummy() { }
208     virtual bool sendMessageToFrontend(const String& message) override;
209
210 private:
211     Page* m_frontendPage;
212 };
213
214 InspectorFrontendChannelDummy::InspectorFrontendChannelDummy(Page* page)
215     : m_frontendPage(page)
216 {
217 }
218
219 bool InspectorFrontendChannelDummy::sendMessageToFrontend(const String& message)
220 {
221     return InspectorClient::doDispatchMessageOnFrontendPage(m_frontendPage, message);
222 }
223 #endif // ENABLE(INSPECTOR)
224
225 static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
226 {
227     if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
228         result = DocumentMarker::AllMarkers();
229     else if (equalIgnoringCase(markerType, "Spelling"))
230         result =  DocumentMarker::Spelling;
231     else if (equalIgnoringCase(markerType, "Grammar"))
232         result =  DocumentMarker::Grammar;
233     else if (equalIgnoringCase(markerType, "TextMatch"))
234         result =  DocumentMarker::TextMatch;
235     else if (equalIgnoringCase(markerType, "Replacement"))
236         result =  DocumentMarker::Replacement;
237     else if (equalIgnoringCase(markerType, "CorrectionIndicator"))
238         result =  DocumentMarker::CorrectionIndicator;
239     else if (equalIgnoringCase(markerType, "RejectedCorrection"))
240         result =  DocumentMarker::RejectedCorrection;
241     else if (equalIgnoringCase(markerType, "Autocorrected"))
242         result =  DocumentMarker::Autocorrected;
243     else if (equalIgnoringCase(markerType, "SpellCheckingExemption"))
244         result =  DocumentMarker::SpellCheckingExemption;
245     else if (equalIgnoringCase(markerType, "DeletedAutocorrection"))
246         result =  DocumentMarker::DeletedAutocorrection;
247     else if (equalIgnoringCase(markerType, "DictationAlternatives"))
248         result =  DocumentMarker::DictationAlternatives;
249 #if ENABLE(TELEPHONE_NUMBER_DETECTION)
250     else if (equalIgnoringCase(markerType, "TelephoneNumber"))
251         result =  DocumentMarker::TelephoneNumber;
252 #endif
253     else
254         return false;
255
256     return true;
257 }
258
259 const char* Internals::internalsId = "internals";
260
261 PassRefPtr<Internals> Internals::create(Document* document)
262 {
263     return adoptRef(new Internals(document));
264 }
265
266 Internals::~Internals()
267 {
268 }
269
270 void Internals::resetToConsistentState(Page* page)
271 {
272     ASSERT(page);
273
274     page->setPageScaleFactor(1, IntPoint(0, 0));
275     page->setPagination(Pagination());
276
277     FrameView* mainFrameView = page->mainFrame().view();
278     if (mainFrameView) {
279         mainFrameView->setHeaderHeight(0);
280         mainFrameView->setFooterHeight(0);
281         page->setTopContentInset(0);
282     }
283
284     TextRun::setAllowsRoundingHacks(false);
285     WebCore::overrideUserPreferredLanguages(Vector<String>());
286     WebCore::Settings::setUsesOverlayScrollbars(false);
287 #if ENABLE(INSPECTOR)
288     page->inspectorController().setProfilerEnabled(false);
289 #endif
290 #if ENABLE(VIDEO_TRACK)
291     page->group().captionPreferences()->setCaptionsStyleSheetOverride(emptyString());
292     page->group().captionPreferences()->setTestingMode(false);
293 #endif
294     if (!page->mainFrame().editor().isContinuousSpellCheckingEnabled())
295         page->mainFrame().editor().toggleContinuousSpellChecking();
296     if (page->mainFrame().editor().isOverwriteModeEnabled())
297         page->mainFrame().editor().toggleOverwriteModeEnabled();
298     cacheStorage().setDefaultOriginQuota(ApplicationCacheStorage::noQuota());
299 #if ENABLE(VIDEO)
300     MediaSessionManager::sharedManager().resetRestrictions();
301 #endif
302 #if HAVE(ACCESSIBILITY)
303     AXObjectCache::setEnhancedUserInterfaceAccessibility(false);
304     AXObjectCache::disableAccessibility();
305 #endif
306
307     MockPageOverlayClient::shared().uninstallAllOverlays();
308 }
309
310 Internals::Internals(Document* document)
311     : ContextDestructionObserver(document)
312 {
313 #if ENABLE(VIDEO_TRACK)
314     if (document && document->page())
315         document->page()->group().captionPreferences()->setTestingMode(true);
316 #endif
317
318 #if ENABLE(MEDIA_STREAM)
319     MockMediaStreamCenter::registerMockMediaStreamCenter();
320     enableMockRTCPeerConnectionHandler();
321     WebCore::provideUserMediaTo(document->page(), new UserMediaClientMock());
322 #endif
323 }
324
325 Document* Internals::contextDocument() const
326 {
327     return downcast<Document>(scriptExecutionContext());
328 }
329
330 Frame* Internals::frame() const
331 {
332     if (!contextDocument())
333         return nullptr;
334     return contextDocument()->frame();
335 }
336
337 InternalSettings* Internals::settings() const
338 {
339     Document* document = contextDocument();
340     if (!document)
341         return 0;
342     Page* page = document->page();
343     if (!page)
344         return 0;
345     return InternalSettings::from(page);
346 }
347
348 unsigned Internals::workerThreadCount() const
349 {
350     return WorkerThread::workerThreadCount();
351 }
352
353 String Internals::address(Node* node)
354 {
355     return String::format("%p", node);
356 }
357
358 bool Internals::nodeNeedsStyleRecalc(Node* node, ExceptionCode& exception)
359 {
360     if (!node) {
361         exception = INVALID_ACCESS_ERR;
362         return false;
363     }
364
365     return node->needsStyleRecalc();
366 }
367
368 String Internals::description(Deprecated::ScriptValue value)
369 {
370     return toString(value.jsValue());
371 }
372
373 bool Internals::isPreloaded(const String& url)
374 {
375     Document* document = contextDocument();
376     return document->cachedResourceLoader()->isPreloaded(url);
377 }
378
379 bool Internals::isLoadingFromMemoryCache(const String& url)
380 {
381     if (!contextDocument() || !contextDocument()->page())
382         return false;
383     CachedResource* resource = memoryCache()->resourceForURL(contextDocument()->completeURL(url), contextDocument()->page()->sessionID());
384     return resource && resource->status() == CachedResource::Cached;
385 }
386
387
388 Node* Internals::treeScopeRootNode(Node* node, ExceptionCode& ec)
389 {
390     if (!node) {
391         ec = INVALID_ACCESS_ERR;
392         return nullptr;
393     }
394
395     return &node->treeScope().rootNode();
396 }
397
398 Node* Internals::parentTreeScope(Node* node, ExceptionCode& ec)
399 {
400     if (!node) {
401         ec = INVALID_ACCESS_ERR;
402         return nullptr;
403     }
404     const TreeScope* parentTreeScope = node->treeScope().parentTreeScope();
405     return parentTreeScope ? &parentTreeScope->rootNode() : nullptr;
406 }
407
408 unsigned Internals::lastSpatialNavigationCandidateCount(ExceptionCode& ec) const
409 {
410     if (!contextDocument() || !contextDocument()->page()) {
411         ec = INVALID_ACCESS_ERR;
412         return 0;
413     }
414
415     return contextDocument()->page()->lastSpatialNavigationCandidateCount();
416 }
417
418 unsigned Internals::numberOfActiveAnimations() const
419 {
420     return frame()->animation().numberOfActiveAnimations(frame()->document());
421 }
422
423 bool Internals::animationsAreSuspended(ExceptionCode& ec) const
424 {
425     Document* document = contextDocument();
426     if (!document || !document->frame()) {
427         ec = INVALID_ACCESS_ERR;
428         return false;
429     }
430
431     return document->frame()->animation().isSuspended();
432 }
433
434 void Internals::suspendAnimations(ExceptionCode& ec) const
435 {
436     Document* document = contextDocument();
437     if (!document || !document->frame()) {
438         ec = INVALID_ACCESS_ERR;
439         return;
440     }
441
442     document->frame()->animation().suspendAnimations();
443 }
444
445 void Internals::resumeAnimations(ExceptionCode& ec) const
446 {
447     Document* document = contextDocument();
448     if (!document || !document->frame()) {
449         ec = INVALID_ACCESS_ERR;
450         return;
451     }
452
453     document->frame()->animation().resumeAnimations();
454 }
455
456 bool Internals::pauseAnimationAtTimeOnElement(const String& animationName, double pauseTime, Element* element, ExceptionCode& ec)
457 {
458     if (!element || pauseTime < 0) {
459         ec = INVALID_ACCESS_ERR;
460         return false;
461     }
462     return frame()->animation().pauseAnimationAtTime(element->renderer(), AtomicString(animationName), pauseTime);
463 }
464
465 bool Internals::pauseAnimationAtTimeOnPseudoElement(const String& animationName, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec)
466 {
467     if (!element || pauseTime < 0) {
468         ec = INVALID_ACCESS_ERR;
469         return false;
470     }
471
472     if (pseudoId != "before" && pseudoId != "after") {
473         ec = INVALID_ACCESS_ERR;
474         return false;
475     }
476
477     PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement();
478     if (!pseudoElement) {
479         ec = INVALID_ACCESS_ERR;
480         return false;
481     }
482
483     return frame()->animation().pauseAnimationAtTime(pseudoElement->renderer(), AtomicString(animationName), pauseTime);
484 }
485
486 bool Internals::pauseTransitionAtTimeOnElement(const String& propertyName, double pauseTime, Element* element, ExceptionCode& ec)
487 {
488     if (!element || pauseTime < 0) {
489         ec = INVALID_ACCESS_ERR;
490         return false;
491     }
492     return frame()->animation().pauseTransitionAtTime(element->renderer(), propertyName, pauseTime);
493 }
494
495 bool Internals::pauseTransitionAtTimeOnPseudoElement(const String& property, double pauseTime, Element* element, const String& pseudoId, ExceptionCode& ec)
496 {
497     if (!element || pauseTime < 0) {
498         ec = INVALID_ACCESS_ERR;
499         return false;
500     }
501
502     if (pseudoId != "before" && pseudoId != "after") {
503         ec = INVALID_ACCESS_ERR;
504         return false;
505     }
506
507     PseudoElement* pseudoElement = pseudoId == "before" ? element->beforePseudoElement() : element->afterPseudoElement();
508     if (!pseudoElement) {
509         ec = INVALID_ACCESS_ERR;
510         return false;
511     }
512
513     return frame()->animation().pauseTransitionAtTime(pseudoElement->renderer(), property, pauseTime);
514 }
515
516 // FIXME: Remove.
517 bool Internals::attached(Node* node, ExceptionCode& ec)
518 {
519     if (!node) {
520         ec = INVALID_ACCESS_ERR;
521         return false;
522     }
523
524     return true;
525 }
526
527 String Internals::elementRenderTreeAsText(Element* element, ExceptionCode& ec)
528 {
529     if (!element) {
530         ec = INVALID_ACCESS_ERR;
531         return String();
532     }
533
534     element->document().updateStyleIfNeeded();
535
536     String representation = externalRepresentation(element);
537     if (representation.isEmpty()) {
538         ec = INVALID_ACCESS_ERR;
539         return String();
540     }
541
542     return representation;
543 }
544
545 PassRefPtr<CSSComputedStyleDeclaration> Internals::computedStyleIncludingVisitedInfo(Node* node, ExceptionCode& ec) const
546 {
547     if (!node) {
548         ec = INVALID_ACCESS_ERR;
549         return 0;
550     }
551
552     bool allowVisitedStyle = true;
553     return CSSComputedStyleDeclaration::create(node, allowVisitedStyle);
554 }
555
556 Node* Internals::ensureShadowRoot(Element* host, ExceptionCode& ec)
557 {
558     if (!host) {
559         ec = INVALID_ACCESS_ERR;
560         return 0;
561     }
562
563     if (ShadowRoot* shadowRoot = host->shadowRoot())
564         return shadowRoot;
565
566     return host->createShadowRoot(ec).get();
567 }
568
569 Node* Internals::createShadowRoot(Element* host, ExceptionCode& ec)
570 {
571     if (!host) {
572         ec = INVALID_ACCESS_ERR;
573         return 0;
574     }
575     return host->createShadowRoot(ec).get();
576 }
577
578 Node* Internals::shadowRoot(Element* host, ExceptionCode& ec)
579 {
580     if (!host) {
581         ec = INVALID_ACCESS_ERR;
582         return nullptr;
583     }
584     return host->shadowRoot();
585 }
586
587 String Internals::shadowRootType(const Node* root, ExceptionCode& ec) const
588 {
589     if (!is<ShadowRoot>(root)) {
590         ec = INVALID_ACCESS_ERR;
591         return String();
592     }
593
594     switch (downcast<ShadowRoot>(*root).type()) {
595     case ShadowRoot::UserAgentShadowRoot:
596         return String("UserAgentShadowRoot");
597     default:
598         ASSERT_NOT_REACHED();
599         return String("Unknown");
600     }
601 }
602
603 Element* Internals::includerFor(Node*, ExceptionCode& ec)
604 {
605     ec = INVALID_ACCESS_ERR;
606     return nullptr;
607 }
608
609 String Internals::shadowPseudoId(Element* element, ExceptionCode& ec)
610 {
611     if (!element) {
612         ec = INVALID_ACCESS_ERR;
613         return String();
614     }
615
616     return element->shadowPseudoId().string();
617 }
618
619 void Internals::setShadowPseudoId(Element* element, const String& id, ExceptionCode& ec)
620 {
621     if (!element) {
622         ec = INVALID_ACCESS_ERR;
623         return;
624     }
625
626     return element->setPseudo(id);
627 }
628
629 String Internals::visiblePlaceholder(Element* element)
630 {
631     if (is<HTMLTextFormControlElement>(element)) {
632         const HTMLTextFormControlElement& textFormControlElement = downcast<HTMLTextFormControlElement>(*element);
633         if (!textFormControlElement.isPlaceholderVisible())
634             return String();
635         if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
636             return placeholderElement->textContent();
637     }
638
639     return String();
640 }
641
642 #if ENABLE(INPUT_TYPE_COLOR)
643 void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
644 {
645     if (!is<HTMLInputElement>(*element))
646         return;
647     HTMLInputElement* inputElement = element->toInputElement();
648     if (!inputElement)
649         return;
650     inputElement->selectColorInColorChooser(Color(colorValue));
651 }
652 #endif
653
654 Vector<String> Internals::formControlStateOfPreviousHistoryItem(ExceptionCode& ec)
655 {
656     HistoryItem* mainItem = frame()->loader().history().previousItem();
657     if (!mainItem) {
658         ec = INVALID_ACCESS_ERR;
659         return Vector<String>();
660     }
661     String uniqueName = frame()->tree().uniqueName();
662     if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) {
663         ec = INVALID_ACCESS_ERR;
664         return Vector<String>();
665     }
666     return mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState();
667 }
668
669 void Internals::setFormControlStateOfPreviousHistoryItem(const Vector<String>& state, ExceptionCode& ec)
670 {
671     HistoryItem* mainItem = frame()->loader().history().previousItem();
672     if (!mainItem) {
673         ec = INVALID_ACCESS_ERR;
674         return;
675     }
676     String uniqueName = frame()->tree().uniqueName();
677     if (mainItem->target() == uniqueName)
678         mainItem->setDocumentState(state);
679     else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName))
680         subItem->setDocumentState(state);
681     else
682         ec = INVALID_ACCESS_ERR;
683 }
684
685 #if ENABLE(SPEECH_SYNTHESIS)
686 void Internals::enableMockSpeechSynthesizer()
687 {
688     Document* document = contextDocument();
689     if (!document || !document->domWindow())
690         return;
691     SpeechSynthesis* synthesis = DOMWindowSpeechSynthesis::speechSynthesis(document->domWindow());
692     if (!synthesis)
693         return;
694     
695     synthesis->setPlatformSynthesizer(std::make_unique<PlatformSpeechSynthesizerMock>(synthesis));
696 }
697 #endif
698
699 #if ENABLE(MEDIA_STREAM)
700 void Internals::enableMockRTCPeerConnectionHandler()
701 {
702     RTCPeerConnectionHandler::create = RTCPeerConnectionHandlerMock::create;
703 }
704 #endif
705
706 PassRefPtr<ClientRect> Internals::absoluteCaretBounds(ExceptionCode& ec)
707 {
708     Document* document = contextDocument();
709     if (!document || !document->frame()) {
710         ec = INVALID_ACCESS_ERR;
711         return ClientRect::create();
712     }
713
714     return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
715 }
716
717 PassRefPtr<ClientRect> Internals::boundingBox(Element* element, ExceptionCode& ec)
718 {
719     if (!element) {
720         ec = INVALID_ACCESS_ERR;
721         return ClientRect::create();
722     }
723
724     element->document().updateLayoutIgnorePendingStylesheets();
725     auto renderer = element->renderer();
726     if (!renderer)
727         return ClientRect::create();
728     return ClientRect::create(renderer->absoluteBoundingBoxRectIgnoringTransforms());
729 }
730
731 PassRefPtr<ClientRectList> Internals::inspectorHighlightRects(ExceptionCode& ec)
732 {
733 #if ENABLE(INSPECTOR)
734     Document* document = contextDocument();
735     if (!document || !document->page()) {
736         ec = INVALID_ACCESS_ERR;
737         return ClientRectList::create();
738     }
739
740     Highlight highlight;
741     document->page()->inspectorController().getHighlight(&highlight, InspectorOverlay::CoordinateSystem::View);
742     return ClientRectList::create(highlight.quads);
743 #else
744     UNUSED_PARAM(ec);
745     return ClientRectList::create();
746 #endif
747 }
748
749 String Internals::inspectorHighlightObject(ExceptionCode& ec)
750 {
751 #if ENABLE(INSPECTOR)
752     Document* document = contextDocument();
753     if (!document || !document->page()) {
754         ec = INVALID_ACCESS_ERR;
755         return String();
756     }
757     RefPtr<InspectorObject> object = document->page()->inspectorController().buildObjectForHighlightedNode();
758     return object ? object->toJSONString() : String();
759 #else
760     UNUSED_PARAM(ec);
761     return String();
762 #endif
763 }
764
765 unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionCode& ec)
766 {
767     if (!node) {
768         ec = INVALID_ACCESS_ERR;
769         return 0;
770     }
771
772     DocumentMarker::MarkerTypes markerTypes = 0;
773     if (!markerTypesFrom(markerType, markerTypes)) {
774         ec = SYNTAX_ERR;
775         return 0;
776     }
777
778     node->document().frame()->editor().updateEditorUINowIfScheduled();
779
780     return node->document().markers().markersFor(node, markerTypes).size();
781 }
782
783 RenderedDocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
784 {
785     node->document().updateLayoutIgnorePendingStylesheets();
786     if (!node) {
787         ec = INVALID_ACCESS_ERR;
788         return nullptr;
789     }
790
791     DocumentMarker::MarkerTypes markerTypes = 0;
792     if (!markerTypesFrom(markerType, markerTypes)) {
793         ec = SYNTAX_ERR;
794         return nullptr;
795     }
796
797     node->document().frame()->editor().updateEditorUINowIfScheduled();
798
799     Vector<RenderedDocumentMarker*> markers = node->document().markers().markersFor(node, markerTypes);
800     if (markers.size() <= index)
801         return nullptr;
802     return markers[index];
803 }
804
805 PassRefPtr<Range> Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
806 {
807     RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
808     if (!marker)
809         return nullptr;
810     return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
811 }
812
813 String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionCode& ec)
814 {
815     RenderedDocumentMarker* marker = markerAt(node, markerType, index, ec);
816     if (!marker)
817         return String();
818     return marker->description();
819 }
820
821 void Internals::addTextMatchMarker(const Range* range, bool isActive)
822 {
823     range->ownerDocument().updateLayoutIgnorePendingStylesheets();
824     range->ownerDocument().markers().addTextMatchMarker(range, isActive);
825 }
826
827 void Internals::setMarkedTextMatchesAreHighlighted(bool flag, ExceptionCode& ec)
828 {
829     Document* document = contextDocument();
830     if (!document || !document->frame()) {
831         ec = INVALID_ACCESS_ERR;
832         return;
833     }
834     document->frame()->editor().setMarkedTextMatchesAreHighlighted(flag);
835 }
836
837 void Internals::invalidateFontCache()
838 {
839     fontCache().invalidate();
840 }
841
842 void Internals::setScrollViewPosition(long x, long y, ExceptionCode& ec)
843 {
844     Document* document = contextDocument();
845     if (!document || !document->view()) {
846         ec = INVALID_ACCESS_ERR;
847         return;
848     }
849
850     FrameView* frameView = document->view();
851     bool constrainsScrollingToContentEdgeOldValue = frameView->constrainsScrollingToContentEdge();
852     bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();
853
854     frameView->setConstrainsScrollingToContentEdge(false);
855     frameView->setScrollbarsSuppressed(false);
856     frameView->setScrollOffsetFromInternals(IntPoint(x, y));
857     frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
858     frameView->setConstrainsScrollingToContentEdge(constrainsScrollingToContentEdgeOldValue);
859 }
860
861 void Internals::setPagination(const String& mode, int gap, int pageLength, ExceptionCode& ec)
862 {
863     Document* document = contextDocument();
864     if (!document || !document->page()) {
865         ec = INVALID_ACCESS_ERR;
866         return;
867     }
868     Page* page = document->page();
869
870     Pagination pagination;
871     if (mode == "Unpaginated")
872         pagination.mode = Pagination::Unpaginated;
873     else if (mode == "LeftToRightPaginated")
874         pagination.mode = Pagination::LeftToRightPaginated;
875     else if (mode == "RightToLeftPaginated")
876         pagination.mode = Pagination::RightToLeftPaginated;
877     else if (mode == "TopToBottomPaginated")
878         pagination.mode = Pagination::TopToBottomPaginated;
879     else if (mode == "BottomToTopPaginated")
880         pagination.mode = Pagination::BottomToTopPaginated;
881     else {
882         ec = SYNTAX_ERR;
883         return;
884     }
885
886     pagination.gap = gap;
887     pagination.pageLength = pageLength;
888     page->setPagination(pagination);
889 }
890
891 String Internals::configurationForViewport(float devicePixelRatio, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight, ExceptionCode& ec)
892 {
893     Document* document = contextDocument();
894     if (!document || !document->page()) {
895         ec = INVALID_ACCESS_ERR;
896         return String();
897     }
898     Page* page = document->page();
899
900     const int defaultLayoutWidthForNonMobilePages = 980;
901
902     ViewportArguments arguments = page->viewportArguments();
903     ViewportAttributes attributes = computeViewportAttributes(arguments, defaultLayoutWidthForNonMobilePages, deviceWidth, deviceHeight, devicePixelRatio, IntSize(availableWidth, availableHeight));
904     restrictMinimumScaleFactorToViewportSize(attributes, IntSize(availableWidth, availableHeight), devicePixelRatio);
905     restrictScaleFactorToInitialScaleIfNotUserScalable(attributes);
906
907     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");
908 }
909
910 bool Internals::wasLastChangeUserEdit(Element* textField, ExceptionCode& ec)
911 {
912     if (!textField) {
913         ec = INVALID_ACCESS_ERR;
914         return false;
915     }
916
917     if (HTMLInputElement* inputElement = textField->toInputElement())
918         return inputElement->lastChangeWasUserEdit();
919
920     if (is<HTMLTextAreaElement>(*textField))
921         return downcast<HTMLTextAreaElement>(*textField).lastChangeWasUserEdit();
922
923     ec = INVALID_NODE_TYPE_ERR;
924     return false;
925 }
926
927 bool Internals::elementShouldAutoComplete(Element* element, ExceptionCode& ec)
928 {
929     if (!element) {
930         ec = INVALID_ACCESS_ERR;
931         return false;
932     }
933
934     if (HTMLInputElement* inputElement = element->toInputElement())
935         return inputElement->shouldAutocomplete();
936
937     ec = INVALID_NODE_TYPE_ERR;
938     return false;
939 }
940
941 void Internals::setEditingValue(Element* element, const String& value, ExceptionCode& ec)
942 {
943     if (!element) {
944         ec = INVALID_ACCESS_ERR;
945         return;
946     }
947
948     HTMLInputElement* inputElement = element->toInputElement();
949     if (!inputElement) {
950         ec = INVALID_NODE_TYPE_ERR;
951         return;
952     }
953
954     inputElement->setEditingValue(value);
955 }
956
957 void Internals::setAutofilled(Element* element, bool enabled, ExceptionCode& ec)
958 {
959     HTMLInputElement* inputElement = element->toInputElement();
960     if (!inputElement) {
961         ec = INVALID_ACCESS_ERR;
962         return;
963     }
964     inputElement->setAutofilled(enabled);
965 }
966
967 void Internals::scrollElementToRect(Element* element, long x, long y, long w, long h, ExceptionCode& ec)
968 {
969     if (!element || !element->document().view()) {
970         ec = INVALID_ACCESS_ERR;
971         return;
972     }
973     FrameView* frameView = element->document().view();
974     frameView->scrollElementToRect(element, IntRect(x, y, w, h));
975 }
976
977 void Internals::paintControlTints(ExceptionCode& ec)
978 {
979     Document* document = contextDocument();
980     if (!document || !document->view()) {
981         ec = INVALID_ACCESS_ERR;
982         return;
983     }
984
985     FrameView* frameView = document->view();
986     frameView->paintControlTints();
987 }
988
989 PassRefPtr<Range> Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength, ExceptionCode& ec)
990 {
991     if (!scope) {
992         ec = INVALID_ACCESS_ERR;
993         return 0;
994     }
995
996     return TextIterator::rangeFromLocationAndLength(scope, rangeLocation, rangeLength);
997 }
998
999 unsigned Internals::locationFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1000 {
1001     if (!scope || !range) {
1002         ec = INVALID_ACCESS_ERR;
1003         return 0;
1004     }
1005
1006     size_t location = 0;
1007     size_t unusedLength = 0;
1008     TextIterator::getLocationAndLengthFromRange(scope, range, location, unusedLength);
1009     return location;
1010 }
1011
1012 unsigned Internals::lengthFromRange(Element* scope, const Range* range, ExceptionCode& ec)
1013 {
1014     if (!scope || !range) {
1015         ec = INVALID_ACCESS_ERR;
1016         return 0;
1017     }
1018
1019     size_t unusedLocation = 0;
1020     size_t length = 0;
1021     TextIterator::getLocationAndLengthFromRange(scope, range, unusedLocation, length);
1022     return length;
1023 }
1024
1025 String Internals::rangeAsText(const Range* range, ExceptionCode& ec)
1026 {
1027     if (!range) {
1028         ec = INVALID_ACCESS_ERR;
1029         return String();
1030     }
1031
1032     return range->text();
1033 }
1034
1035 void Internals::setDelegatesScrolling(bool enabled, ExceptionCode& ec)
1036 {
1037     Document* document = contextDocument();
1038     // Delegate scrolling is valid only on mainframe's view.
1039     if (!document || !document->view() || !document->page() || &document->page()->mainFrame() != document->frame()) {
1040         ec = INVALID_ACCESS_ERR;
1041         return;
1042     }
1043
1044     document->view()->setDelegatesScrolling(enabled);
1045 }
1046
1047 int Internals::lastSpellCheckRequestSequence(ExceptionCode& ec)
1048 {
1049     Document* document = contextDocument();
1050     if (!document || !document->frame()) {
1051         ec = INVALID_ACCESS_ERR;
1052         return -1;
1053     }
1054
1055     return document->frame()->editor().spellChecker().lastRequestSequence();
1056 }
1057
1058 int Internals::lastSpellCheckProcessedSequence(ExceptionCode& ec)
1059 {
1060     Document* document = contextDocument();
1061     if (!document || !document->frame()) {
1062         ec = INVALID_ACCESS_ERR;
1063         return -1;
1064     }
1065
1066     return document->frame()->editor().spellChecker().lastProcessedSequence();
1067 }
1068
1069 Vector<String> Internals::userPreferredLanguages() const
1070 {
1071     return WebCore::userPreferredLanguages();
1072 }
1073
1074 void Internals::setUserPreferredLanguages(const Vector<String>& languages)
1075 {
1076     WebCore::overrideUserPreferredLanguages(languages);
1077 }
1078
1079 unsigned Internals::wheelEventHandlerCount(ExceptionCode& ec)
1080 {
1081     Document* document = contextDocument();
1082     if (!document) {
1083         ec = INVALID_ACCESS_ERR;
1084         return 0;
1085     }
1086
1087     return document->wheelEventHandlerCount();
1088 }
1089
1090 unsigned Internals::touchEventHandlerCount(ExceptionCode& ec)
1091 {
1092     Document* document = contextDocument();
1093     if (!document) {
1094         ec = INVALID_ACCESS_ERR;
1095         return 0;
1096     }
1097
1098     const TouchEventTargetSet* touchHandlers = document->touchEventTargets();
1099     if (!touchHandlers)
1100         return 0;
1101
1102     unsigned count = 0;
1103     for (TouchEventTargetSet::const_iterator iter = touchHandlers->begin(); iter != touchHandlers->end(); ++iter)
1104         count += iter->value;
1105     return count;
1106 }
1107
1108 // FIXME: Remove the document argument. It is almost always the same as
1109 // contextDocument(), with the exception of a few tests that pass a
1110 // different document, and could just make the call through another Internals
1111 // instance instead.
1112 PassRefPtr<NodeList> Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
1113     unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowShadowContent, bool allowChildFrameContent, ExceptionCode& ec) const
1114 {
1115     if (!document || !document->frame() || !document->frame()->view()) {
1116         ec = INVALID_ACCESS_ERR;
1117         return 0;
1118     }
1119
1120     Frame* frame = document->frame();
1121     FrameView* frameView = document->view();
1122     RenderView* renderView = document->renderView();
1123     if (!renderView)
1124         return 0;
1125
1126     document->updateLayoutIgnorePendingStylesheets();
1127
1128     float zoomFactor = frame->pageZoomFactor();
1129     LayoutPoint point(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY());
1130
1131     HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
1132     if (ignoreClipping)
1133         hitType |= HitTestRequest::IgnoreClipping;
1134     if (!allowShadowContent)
1135         hitType |= HitTestRequest::DisallowShadowContent;
1136     if (allowChildFrameContent)
1137         hitType |= HitTestRequest::AllowChildFrameContent;
1138
1139     HitTestRequest request(hitType);
1140
1141     // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
1142     if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
1143         return 0;
1144
1145     Vector<Ref<Node>> matches;
1146
1147     // Need padding to trigger a rect based hit test, but we want to return a NodeList
1148     // so we special case this.
1149     if (!topPadding && !rightPadding && !bottomPadding && !leftPadding) {
1150         HitTestResult result(point);
1151         renderView->hitTest(request, result);
1152         if (result.innerNode())
1153             matches.append(*result.innerNode()->deprecatedShadowAncestorNode());
1154     } else {
1155         HitTestResult result(point, topPadding, rightPadding, bottomPadding, leftPadding);
1156         renderView->hitTest(request, result);
1157         
1158         const HitTestResult::NodeSet& nodeSet = result.rectBasedTestResult();
1159         matches.reserveInitialCapacity(nodeSet.size());
1160         for (auto it = nodeSet.begin(), end = nodeSet.end(); it != end; ++it)
1161             matches.uncheckedAppend(*it->get());
1162     }
1163
1164     return StaticNodeList::adopt(matches);
1165 }
1166
1167 class GetCallerCodeBlockFunctor {
1168 public:
1169     GetCallerCodeBlockFunctor()
1170         : m_iterations(0)
1171         , m_codeBlock(0)
1172     {
1173     }
1174
1175     StackVisitor::Status operator()(StackVisitor& visitor)
1176     {
1177         ++m_iterations;
1178         if (m_iterations < 2)
1179             return StackVisitor::Continue;
1180
1181         m_codeBlock = visitor->codeBlock();
1182         return StackVisitor::Done;
1183     }
1184
1185     CodeBlock* codeBlock() const { return m_codeBlock; }
1186
1187 private:
1188     int m_iterations;
1189     CodeBlock* m_codeBlock;
1190 };
1191
1192 String Internals::parserMetaData(Deprecated::ScriptValue value)
1193 {
1194     JSC::VM& vm = contextDocument()->vm();
1195     JSC::ExecState* exec = vm.topCallFrame;
1196     JSC::JSValue code = value.jsValue();
1197     ScriptExecutable* executable;
1198
1199     if (!code || code.isNull() || code.isUndefined()) {
1200         GetCallerCodeBlockFunctor iter;
1201         exec->iterate(iter);
1202         CodeBlock* codeBlock = iter.codeBlock();
1203         executable = codeBlock->ownerExecutable(); 
1204     } else if (code.isFunction()) {
1205         JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec));
1206         executable = funcObj->jsExecutable();
1207     } else
1208         return String();
1209
1210     unsigned startLine = executable->lineNo();
1211     unsigned startColumn = executable->startColumn();
1212     unsigned endLine = executable->lastLine();
1213     unsigned endColumn = executable->endColumn();
1214
1215     StringBuilder result;
1216
1217     if (executable->isFunctionExecutable()) {
1218         FunctionExecutable* funcExecutable = reinterpret_cast<FunctionExecutable*>(executable);
1219         String inferredName = funcExecutable->inferredName().string();
1220         result.appendLiteral("function \"");
1221         result.append(inferredName);
1222         result.append('"');
1223     } else if (executable->isEvalExecutable())
1224         result.appendLiteral("eval");
1225     else {
1226         ASSERT(executable->isProgramExecutable());
1227         result.appendLiteral("program");
1228     }
1229
1230     result.appendLiteral(" { ");
1231     result.appendNumber(startLine);
1232     result.append(':');
1233     result.appendNumber(startColumn);
1234     result.appendLiteral(" - ");
1235     result.appendNumber(endLine);
1236     result.append(':');
1237     result.appendNumber(endColumn);
1238     result.appendLiteral(" }");
1239
1240     return result.toString();
1241 }
1242
1243 void Internals::setBatteryStatus(const String& eventType, bool charging, double chargingTime, double dischargingTime, double level, ExceptionCode& ec)
1244 {
1245     Document* document = contextDocument();
1246     if (!document || !document->page()) {
1247         ec = INVALID_ACCESS_ERR;
1248         return;
1249     }
1250
1251 #if ENABLE(BATTERY_STATUS)
1252     BatteryController::from(document->page())->didChangeBatteryStatus(eventType, BatteryStatus::create(charging, chargingTime, dischargingTime, level));
1253 #else
1254     UNUSED_PARAM(eventType);
1255     UNUSED_PARAM(charging);
1256     UNUSED_PARAM(chargingTime);
1257     UNUSED_PARAM(dischargingTime);
1258     UNUSED_PARAM(level);
1259 #endif
1260 }
1261
1262 void Internals::setDeviceProximity(const String& eventType, double value, double min, double max, ExceptionCode& ec)
1263 {
1264     Document* document = contextDocument();
1265     if (!document || !document->page()) {
1266         ec = INVALID_ACCESS_ERR;
1267         return;
1268     }
1269
1270 #if ENABLE(PROXIMITY_EVENTS)
1271     DeviceProximityController::from(document->page())->didChangeDeviceProximity(value, min, max);
1272 #else
1273     UNUSED_PARAM(eventType);
1274     UNUSED_PARAM(value);
1275     UNUSED_PARAM(min);
1276     UNUSED_PARAM(max);
1277 #endif
1278 }
1279
1280 void Internals::updateEditorUINowIfScheduled()
1281 {
1282     if (Document* document = contextDocument()) {
1283         if (Frame* frame = document->frame())
1284             frame->editor().updateEditorUINowIfScheduled();
1285     }
1286 }
1287
1288 Node* Internals::findEditingDeleteButton()
1289 {
1290     Document* document = contextDocument();
1291     if (!document || !document->frame())
1292         return 0;
1293
1294     updateEditorUINowIfScheduled();
1295
1296     // FIXME: We shouldn't pollute the id namespace with this name.
1297     return document->getElementById(String(ASCIILiteral("WebKit-Editing-Delete-Button")));
1298 }
1299
1300 bool Internals::hasSpellingMarker(int from, int length, ExceptionCode&)
1301 {
1302     Document* document = contextDocument();
1303     if (!document || !document->frame())
1304         return 0;
1305
1306     updateEditorUINowIfScheduled();
1307
1308     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
1309 }
1310     
1311 bool Internals::hasAutocorrectedMarker(int from, int length, ExceptionCode&)
1312 {
1313     Document* document = contextDocument();
1314     if (!document || !document->frame())
1315         return 0;
1316
1317     updateEditorUINowIfScheduled();
1318
1319     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Autocorrected, from, length);
1320 }
1321
1322 void Internals::setContinuousSpellCheckingEnabled(bool enabled, ExceptionCode&)
1323 {
1324     if (!contextDocument() || !contextDocument()->frame())
1325         return;
1326
1327     if (enabled != contextDocument()->frame()->editor().isContinuousSpellCheckingEnabled())
1328         contextDocument()->frame()->editor().toggleContinuousSpellChecking();
1329 }
1330
1331 void Internals::setAutomaticQuoteSubstitutionEnabled(bool enabled, ExceptionCode&)
1332 {
1333     if (!contextDocument() || !contextDocument()->frame())
1334         return;
1335
1336 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1337     if (enabled != contextDocument()->frame()->editor().isAutomaticQuoteSubstitutionEnabled())
1338         contextDocument()->frame()->editor().toggleAutomaticQuoteSubstitution();
1339 #else
1340     UNUSED_PARAM(enabled);
1341 #endif
1342 }
1343
1344 void Internals::setAutomaticLinkDetectionEnabled(bool enabled, ExceptionCode&)
1345 {
1346     if (!contextDocument() || !contextDocument()->frame())
1347         return;
1348
1349 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1350     if (enabled != contextDocument()->frame()->editor().isAutomaticLinkDetectionEnabled())
1351         contextDocument()->frame()->editor().toggleAutomaticLinkDetection();
1352 #else
1353     UNUSED_PARAM(enabled);
1354 #endif
1355 }
1356
1357 void Internals::setAutomaticDashSubstitutionEnabled(bool enabled, ExceptionCode&)
1358 {
1359     if (!contextDocument() || !contextDocument()->frame())
1360         return;
1361
1362 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1363     if (enabled != contextDocument()->frame()->editor().isAutomaticDashSubstitutionEnabled())
1364         contextDocument()->frame()->editor().toggleAutomaticDashSubstitution();
1365 #else
1366     UNUSED_PARAM(enabled);
1367 #endif
1368 }
1369
1370 void Internals::setAutomaticTextReplacementEnabled(bool enabled, ExceptionCode&)
1371 {
1372     if (!contextDocument() || !contextDocument()->frame())
1373         return;
1374
1375 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1376     if (enabled != contextDocument()->frame()->editor().isAutomaticTextReplacementEnabled())
1377         contextDocument()->frame()->editor().toggleAutomaticTextReplacement();
1378 #else
1379     UNUSED_PARAM(enabled);
1380 #endif
1381 }
1382
1383 void Internals::setAutomaticSpellingCorrectionEnabled(bool enabled, ExceptionCode&)
1384 {
1385     if (!contextDocument() || !contextDocument()->frame())
1386         return;
1387
1388 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
1389     if (enabled != contextDocument()->frame()->editor().isAutomaticSpellingCorrectionEnabled())
1390         contextDocument()->frame()->editor().toggleAutomaticSpellingCorrection();
1391 #else
1392     UNUSED_PARAM(enabled);
1393 #endif
1394 }
1395
1396 bool Internals::isOverwriteModeEnabled(ExceptionCode&)
1397 {
1398     Document* document = contextDocument();
1399     if (!document || !document->frame())
1400         return 0;
1401
1402     return document->frame()->editor().isOverwriteModeEnabled();
1403 }
1404
1405 void Internals::toggleOverwriteModeEnabled(ExceptionCode&)
1406 {
1407     Document* document = contextDocument();
1408     if (!document || !document->frame())
1409         return;
1410
1411     document->frame()->editor().toggleOverwriteModeEnabled();
1412 }
1413
1414 unsigned Internals::countMatchesForText(const String& text, unsigned findOptions, const String& markMatches, ExceptionCode&)
1415 {
1416     Document* document = contextDocument();
1417     if (!document || !document->frame())
1418         return 0;
1419
1420     bool mark = markMatches == "mark";
1421     return document->frame()->editor().countMatchesForText(text, nullptr, findOptions, 1000, mark, nullptr);
1422 }
1423
1424 const ProfilesArray& Internals::consoleProfiles() const
1425 {
1426     return contextDocument()->page()->console().profiles();
1427 }
1428
1429 unsigned Internals::numberOfLiveNodes() const
1430 {
1431     unsigned nodeCount = 0;
1432     for (auto* document : Document::allDocuments())
1433         nodeCount += document->referencingNodeCount();
1434     return nodeCount;
1435 }
1436
1437 unsigned Internals::numberOfLiveDocuments() const
1438 {
1439     return Document::allDocuments().size();
1440 }
1441
1442 #if ENABLE(INSPECTOR)
1443 Vector<String> Internals::consoleMessageArgumentCounts() const
1444 {
1445     Document* document = contextDocument();
1446     if (!document || !document->page())
1447         return Vector<String>();
1448
1449     InstrumentingAgents* instrumentingAgents = instrumentationForPage(document->page());
1450     if (!instrumentingAgents)
1451         return Vector<String>();
1452
1453     InspectorConsoleAgent* consoleAgent = instrumentingAgents->webConsoleAgent();
1454     if (!consoleAgent)
1455         return Vector<String>();
1456
1457     Vector<unsigned> counts = consoleAgent->consoleMessageArgumentCounts();
1458     Vector<String> result(counts.size());
1459     for (size_t i = 0; i < counts.size(); i++)
1460         result[i] = String::number(counts[i]);
1461     return result;
1462 }
1463
1464 PassRefPtr<DOMWindow> Internals::openDummyInspectorFrontend(const String& url)
1465 {
1466     Page* page = contextDocument()->frame()->page();
1467     ASSERT(page);
1468
1469     DOMWindow* window = page->mainFrame().document()->domWindow();
1470     ASSERT(window);
1471
1472     m_frontendWindow = window->open(url, "", "", *window, *window);
1473     ASSERT(m_frontendWindow);
1474
1475     Page* frontendPage = m_frontendWindow->document()->page();
1476     ASSERT(frontendPage);
1477
1478     m_frontendClient = std::make_unique<InspectorFrontendClientDummy>(&page->inspectorController(), frontendPage);
1479     frontendPage->inspectorController().setInspectorFrontendClient(m_frontendClient.get());
1480
1481     bool isAutomaticInspection = false;
1482     m_frontendChannel = std::make_unique<InspectorFrontendChannelDummy>(frontendPage);
1483     page->inspectorController().connectFrontend(m_frontendChannel.get(), isAutomaticInspection);
1484
1485     return m_frontendWindow;
1486 }
1487
1488 void Internals::closeDummyInspectorFrontend()
1489 {
1490     Page* page = contextDocument()->frame()->page();
1491     ASSERT(page);
1492     ASSERT(m_frontendWindow);
1493
1494     page->inspectorController().disconnectFrontend(InspectorDisconnectReason::InspectorDestroyed);
1495
1496     m_frontendClient = nullptr;
1497     m_frontendChannel = nullptr;
1498
1499     m_frontendWindow->close(m_frontendWindow->scriptExecutionContext());
1500     m_frontendWindow.clear();
1501 }
1502
1503 void Internals::setJavaScriptProfilingEnabled(bool enabled, ExceptionCode& ec)
1504 {
1505     Page* page = contextDocument()->frame()->page();
1506     if (!page) {
1507         ec = INVALID_ACCESS_ERR;
1508         return;
1509     }
1510
1511     page->inspectorController().setProfilerEnabled(enabled);
1512 }
1513
1514 void Internals::setInspectorIsUnderTest(bool isUnderTest, ExceptionCode& ec)
1515 {
1516     Page* page = contextDocument()->frame()->page();
1517     if (!page) {
1518         ec = INVALID_ACCESS_ERR;
1519         return;
1520     }
1521
1522     page->inspectorController().setIsUnderTest(isUnderTest);
1523 }
1524 #endif // ENABLE(INSPECTOR)
1525
1526 bool Internals::hasGrammarMarker(int from, int length, ExceptionCode&)
1527 {
1528     Document* document = contextDocument();
1529     if (!document || !document->frame())
1530         return 0;
1531
1532     return document->frame()->editor().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
1533 }
1534
1535 unsigned Internals::numberOfScrollableAreas(ExceptionCode&)
1536 {
1537     Document* document = contextDocument();
1538     if (!document || !document->frame())
1539         return 0;
1540
1541     unsigned count = 0;
1542     Frame* frame = document->frame();
1543     if (frame->view()->scrollableAreas())
1544         count += frame->view()->scrollableAreas()->size();
1545
1546     for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
1547         if (child->view() && child->view()->scrollableAreas())
1548             count += child->view()->scrollableAreas()->size();
1549     }
1550
1551     return count;
1552 }
1553     
1554 bool Internals::isPageBoxVisible(int pageNumber, ExceptionCode& ec)
1555 {
1556     Document* document = contextDocument();
1557     if (!document) {
1558         ec = INVALID_ACCESS_ERR;
1559         return false;
1560     }
1561
1562     return document->isPageBoxVisible(pageNumber);
1563 }
1564
1565 // FIXME: Remove the document argument. It is almost always the same as
1566 // contextDocument(), with the exception of a few tests that pass a
1567 // different document, and could just make the call through another Internals
1568 // instance instead.
1569 String Internals::layerTreeAsText(Document* document, ExceptionCode& ec) const
1570 {
1571     return layerTreeAsText(document, 0, ec);
1572 }
1573
1574 String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionCode& ec) const
1575 {
1576     if (!document || !document->frame()) {
1577         ec = INVALID_ACCESS_ERR;
1578         return String();
1579     }
1580
1581     LayerTreeFlags layerTreeFlags = 0;
1582     if (flags & LAYER_TREE_INCLUDES_VISIBLE_RECTS)
1583         layerTreeFlags |= LayerTreeFlagsIncludeVisibleRects;
1584     if (flags & LAYER_TREE_INCLUDES_TILE_CACHES)
1585         layerTreeFlags |= LayerTreeFlagsIncludeTileCaches;
1586     if (flags & LAYER_TREE_INCLUDES_REPAINT_RECTS)
1587         layerTreeFlags |= LayerTreeFlagsIncludeRepaintRects;
1588     if (flags & LAYER_TREE_INCLUDES_PAINTING_PHASES)
1589         layerTreeFlags |= LayerTreeFlagsIncludePaintingPhases;
1590     if (flags & LAYER_TREE_INCLUDES_CONTENT_LAYERS)
1591         layerTreeFlags |= LayerTreeFlagsIncludeContentLayers;
1592
1593     return document->frame()->layerTreeAsText(layerTreeFlags);
1594 }
1595
1596 String Internals::repaintRectsAsText(ExceptionCode& ec) const
1597 {
1598     Document* document = contextDocument();
1599     if (!document || !document->frame()) {
1600         ec = INVALID_ACCESS_ERR;
1601         return String();
1602     }
1603
1604     return document->frame()->trackedRepaintRectsAsText();
1605 }
1606
1607 String Internals::scrollingStateTreeAsText(ExceptionCode& ec) const
1608 {
1609     Document* document = contextDocument();
1610     if (!document || !document->frame()) {
1611         ec = INVALID_ACCESS_ERR;
1612         return String();
1613     }
1614
1615     Page* page = document->page();
1616     if (!page)
1617         return String();
1618
1619     return page->scrollingStateTreeAsText();
1620 }
1621
1622 String Internals::mainThreadScrollingReasons(ExceptionCode& ec) const
1623 {
1624     Document* document = contextDocument();
1625     if (!document || !document->frame()) {
1626         ec = INVALID_ACCESS_ERR;
1627         return String();
1628     }
1629
1630     Page* page = document->page();
1631     if (!page)
1632         return String();
1633
1634     return page->synchronousScrollingReasonsAsText();
1635 }
1636
1637 PassRefPtr<ClientRectList> Internals::nonFastScrollableRects(ExceptionCode& ec) const
1638 {
1639     Document* document = contextDocument();
1640     if (!document || !document->frame()) {
1641         ec = INVALID_ACCESS_ERR;
1642         return 0;
1643     }
1644
1645     Page* page = document->page();
1646     if (!page)
1647         return 0;
1648
1649     return page->nonFastScrollableRects(document->frame());
1650 }
1651
1652 void Internals::garbageCollectDocumentResources(ExceptionCode& ec) const
1653 {
1654     Document* document = contextDocument();
1655     if (!document) {
1656         ec = INVALID_ACCESS_ERR;
1657         return;
1658     }
1659
1660     CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
1661     if (!cachedResourceLoader)
1662         return;
1663     cachedResourceLoader->garbageCollectDocumentResources();
1664 }
1665
1666 void Internals::allowRoundingHacks() const
1667 {
1668     TextRun::setAllowsRoundingHacks(true);
1669 }
1670
1671 void Internals::insertAuthorCSS(const String& css, ExceptionCode& ec) const
1672 {
1673     Document* document = contextDocument();
1674     if (!document) {
1675         ec = INVALID_ACCESS_ERR;
1676         return;
1677     }
1678
1679     auto parsedSheet = StyleSheetContents::create(*document);
1680     parsedSheet.get().setIsUserStyleSheet(false);
1681     parsedSheet.get().parseString(css);
1682     document->styleSheetCollection().addAuthorSheet(WTF::move(parsedSheet));
1683 }
1684
1685 void Internals::insertUserCSS(const String& css, ExceptionCode& ec) const
1686 {
1687     Document* document = contextDocument();
1688     if (!document) {
1689         ec = INVALID_ACCESS_ERR;
1690         return;
1691     }
1692
1693     auto parsedSheet = StyleSheetContents::create(*document);
1694     parsedSheet.get().setIsUserStyleSheet(true);
1695     parsedSheet.get().parseString(css);
1696     document->styleSheetCollection().addUserSheet(WTF::move(parsedSheet));
1697 }
1698
1699 String Internals::counterValue(Element* element)
1700 {
1701     if (!element)
1702         return String();
1703
1704     return counterValueForElement(element);
1705 }
1706
1707 int Internals::pageNumber(Element* element, float pageWidth, float pageHeight)
1708 {
1709     if (!element)
1710         return 0;
1711
1712     return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
1713 }
1714
1715 Vector<String> Internals::iconURLs(Document* document, int iconTypesMask) const
1716 {
1717     Vector<IconURL> iconURLs = document->iconURLs(iconTypesMask);
1718     Vector<String> array;
1719
1720     Vector<IconURL>::const_iterator iter(iconURLs.begin());
1721     for (; iter != iconURLs.end(); ++iter)
1722         array.append(iter->m_iconURL.string());
1723
1724     return array;
1725 }
1726
1727 Vector<String> Internals::shortcutIconURLs() const
1728 {
1729     return iconURLs(contextDocument(), Favicon);
1730 }
1731
1732 Vector<String> Internals::allIconURLs() const
1733 {
1734     return iconURLs(contextDocument(), Favicon | TouchIcon | TouchPrecomposedIcon);
1735 }
1736
1737 int Internals::numberOfPages(float pageWidth, float pageHeight)
1738 {
1739     if (!frame())
1740         return -1;
1741
1742     return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
1743 }
1744
1745 String Internals::pageProperty(String propertyName, int pageNumber, ExceptionCode& ec) const
1746 {
1747     if (!frame()) {
1748         ec = INVALID_ACCESS_ERR;
1749         return String();
1750     }
1751
1752     return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
1753 }
1754
1755 String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionCode& ec) const
1756 {
1757     if (!frame()) {
1758         ec = INVALID_ACCESS_ERR;
1759         return String();
1760     }
1761
1762     return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
1763 }
1764
1765 void Internals::setPageScaleFactor(float scaleFactor, int x, int y, ExceptionCode& ec)
1766 {
1767     Document* document = contextDocument();
1768     if (!document || !document->page()) {
1769         ec = INVALID_ACCESS_ERR;
1770         return;
1771     }
1772     Page* page = document->page();
1773     page->setPageScaleFactor(scaleFactor, IntPoint(x, y));
1774 }
1775
1776 void Internals::setPageZoomFactor(float zoomFactor, ExceptionCode& ec)
1777 {
1778     Document* document = contextDocument();
1779     if (!document || !document->frame()) {
1780         ec = INVALID_ACCESS_ERR;
1781         return;
1782     }
1783     Frame* frame = document->frame();
1784     frame->setPageZoomFactor(zoomFactor);
1785 }
1786
1787 void Internals::setHeaderHeight(float height)
1788 {
1789     Document* document = contextDocument();
1790     if (!document || !document->view())
1791         return;
1792
1793     FrameView* frameView = document->view();
1794     frameView->setHeaderHeight(height);
1795 }
1796
1797 void Internals::setFooterHeight(float height)
1798 {
1799     Document* document = contextDocument();
1800     if (!document || !document->view())
1801         return;
1802
1803     FrameView* frameView = document->view();
1804     frameView->setFooterHeight(height);
1805 }
1806     
1807 void Internals::setTopContentInset(float contentInset)
1808 {
1809     Document* document = contextDocument();
1810     if (!document)
1811         return;
1812     
1813     Page* page = document->page();
1814     page->setTopContentInset(contentInset);
1815 }
1816
1817 #if ENABLE(FULLSCREEN_API)
1818 void Internals::webkitWillEnterFullScreenForElement(Element* element)
1819 {
1820     Document* document = contextDocument();
1821     if (!document)
1822         return;
1823     document->webkitWillEnterFullScreenForElement(element);
1824 }
1825
1826 void Internals::webkitDidEnterFullScreenForElement(Element* element)
1827 {
1828     Document* document = contextDocument();
1829     if (!document)
1830         return;
1831     document->webkitDidEnterFullScreenForElement(element);
1832 }
1833
1834 void Internals::webkitWillExitFullScreenForElement(Element* element)
1835 {
1836     Document* document = contextDocument();
1837     if (!document)
1838         return;
1839     document->webkitWillExitFullScreenForElement(element);
1840 }
1841
1842 void Internals::webkitDidExitFullScreenForElement(Element* element)
1843 {
1844     Document* document = contextDocument();
1845     if (!document)
1846         return;
1847     document->webkitDidExitFullScreenForElement(element);
1848 }
1849 #endif
1850
1851 void Internals::setApplicationCacheOriginQuota(unsigned long long quota)
1852 {
1853     Document* document = contextDocument();
1854     if (!document)
1855         return;
1856     cacheStorage().storeUpdatedQuotaForOrigin(document->securityOrigin(), quota);
1857 }
1858
1859 void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
1860 {
1861     SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
1862 }
1863
1864 void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
1865 {
1866     SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
1867 }
1868
1869 PassRefPtr<MallocStatistics> Internals::mallocStatistics() const
1870 {
1871     return MallocStatistics::create();
1872 }
1873
1874 PassRefPtr<TypeConversions> Internals::typeConversions() const
1875 {
1876     return TypeConversions::create();
1877 }
1878
1879 PassRefPtr<MemoryInfo> Internals::memoryInfo() const
1880 {
1881     return MemoryInfo::create();
1882 }
1883
1884 Vector<String> Internals::getReferencedFilePaths() const
1885 {
1886     frame()->loader().history().saveDocumentAndScrollState();
1887     return FormController::getReferencedFilePaths(frame()->loader().history().currentItem()->documentState());
1888 }
1889
1890 void Internals::startTrackingRepaints(ExceptionCode& ec)
1891 {
1892     Document* document = contextDocument();
1893     if (!document || !document->view()) {
1894         ec = INVALID_ACCESS_ERR;
1895         return;
1896     }
1897
1898     FrameView* frameView = document->view();
1899     frameView->setTracksRepaints(true);
1900 }
1901
1902 void Internals::stopTrackingRepaints(ExceptionCode& ec)
1903 {
1904     Document* document = contextDocument();
1905     if (!document || !document->view()) {
1906         ec = INVALID_ACCESS_ERR;
1907         return;
1908     }
1909
1910     FrameView* frameView = document->view();
1911     frameView->setTracksRepaints(false);
1912 }
1913
1914 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(ExceptionCode& ec)
1915 {
1916     updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(nullptr, ec);
1917 }
1918
1919 void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionCode& ec)
1920 {
1921     Document* document;
1922     if (!node)
1923         document = contextDocument();
1924     else if (is<Document>(*node))
1925         document = downcast<Document>(node);
1926     else if (is<HTMLIFrameElement>(*node))
1927         document = downcast<HTMLIFrameElement>(*node).contentDocument();
1928     else {
1929         ec = TypeError;
1930         return;
1931     }
1932
1933     document->updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks::Synchronously);
1934 }
1935
1936 #if !PLATFORM(IOS)
1937 static const char* cursorTypeToString(Cursor::Type cursorType)
1938 {
1939     switch (cursorType) {
1940     case Cursor::Pointer: return "Pointer";
1941     case Cursor::Cross: return "Cross";
1942     case Cursor::Hand: return "Hand";
1943     case Cursor::IBeam: return "IBeam";
1944     case Cursor::Wait: return "Wait";
1945     case Cursor::Help: return "Help";
1946     case Cursor::EastResize: return "EastResize";
1947     case Cursor::NorthResize: return "NorthResize";
1948     case Cursor::NorthEastResize: return "NorthEastResize";
1949     case Cursor::NorthWestResize: return "NorthWestResize";
1950     case Cursor::SouthResize: return "SouthResize";
1951     case Cursor::SouthEastResize: return "SouthEastResize";
1952     case Cursor::SouthWestResize: return "SouthWestResize";
1953     case Cursor::WestResize: return "WestResize";
1954     case Cursor::NorthSouthResize: return "NorthSouthResize";
1955     case Cursor::EastWestResize: return "EastWestResize";
1956     case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
1957     case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
1958     case Cursor::ColumnResize: return "ColumnResize";
1959     case Cursor::RowResize: return "RowResize";
1960     case Cursor::MiddlePanning: return "MiddlePanning";
1961     case Cursor::EastPanning: return "EastPanning";
1962     case Cursor::NorthPanning: return "NorthPanning";
1963     case Cursor::NorthEastPanning: return "NorthEastPanning";
1964     case Cursor::NorthWestPanning: return "NorthWestPanning";
1965     case Cursor::SouthPanning: return "SouthPanning";
1966     case Cursor::SouthEastPanning: return "SouthEastPanning";
1967     case Cursor::SouthWestPanning: return "SouthWestPanning";
1968     case Cursor::WestPanning: return "WestPanning";
1969     case Cursor::Move: return "Move";
1970     case Cursor::VerticalText: return "VerticalText";
1971     case Cursor::Cell: return "Cell";
1972     case Cursor::ContextMenu: return "ContextMenu";
1973     case Cursor::Alias: return "Alias";
1974     case Cursor::Progress: return "Progress";
1975     case Cursor::NoDrop: return "NoDrop";
1976     case Cursor::Copy: return "Copy";
1977     case Cursor::None: return "None";
1978     case Cursor::NotAllowed: return "NotAllowed";
1979     case Cursor::ZoomIn: return "ZoomIn";
1980     case Cursor::ZoomOut: return "ZoomOut";
1981     case Cursor::Grab: return "Grab";
1982     case Cursor::Grabbing: return "Grabbing";
1983     case Cursor::Custom: return "Custom";
1984     }
1985
1986     ASSERT_NOT_REACHED();
1987     return "UNKNOWN";
1988 }
1989 #endif
1990
1991 String Internals::getCurrentCursorInfo(ExceptionCode& ec)
1992 {
1993     Document* document = contextDocument();
1994     if (!document || !document->frame()) {
1995         ec = INVALID_ACCESS_ERR;
1996         return String();
1997     }
1998
1999 #if !PLATFORM(IOS)
2000     Cursor cursor = document->frame()->eventHandler().currentMouseCursor();
2001
2002     StringBuilder result;
2003     result.appendLiteral("type=");
2004     result.append(cursorTypeToString(cursor.type()));
2005     result.appendLiteral(" hotSpot=");
2006     result.appendNumber(cursor.hotSpot().x());
2007     result.append(',');
2008     result.appendNumber(cursor.hotSpot().y());
2009     if (cursor.image()) {
2010         FloatSize size = cursor.image()->size();
2011         result.appendLiteral(" image=");
2012         result.appendNumber(size.width());
2013         result.append('x');
2014         result.appendNumber(size.height());
2015     }
2016 #if ENABLE(MOUSE_CURSOR_SCALE)
2017     if (cursor.imageScaleFactor() != 1) {
2018         result.appendLiteral(" scale=");
2019         NumberToStringBuffer buffer;
2020         result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
2021     }
2022 #endif
2023     return result.toString();
2024 #else
2025     return "FAIL: Cursor details not available on this platform.";
2026 #endif
2027 }
2028
2029 PassRefPtr<ArrayBuffer> Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
2030 {
2031     Vector<uint8_t> bytes = value->data();
2032     return ArrayBuffer::create(bytes.data(), bytes.size());
2033 }
2034
2035 PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(PassRefPtr<ArrayBuffer> buffer) const
2036 {
2037     Vector<uint8_t> bytes;
2038     bytes.append(static_cast<const uint8_t*>(buffer->data()), buffer->byteLength());
2039     return SerializedScriptValue::adopt(bytes);
2040 }
2041
2042 void Internals::setUsesOverlayScrollbars(bool enabled)
2043 {
2044     WebCore::Settings::setUsesOverlayScrollbars(enabled);
2045 }
2046
2047 void Internals::forceReload(bool endToEnd)
2048 {
2049     frame()->loader().reload(endToEnd);
2050 }
2051
2052 #if ENABLE(ENCRYPTED_MEDIA_V2)
2053 void Internals::initializeMockCDM()
2054 {
2055     CDM::registerCDMFactory(MockCDM::create, MockCDM::supportsKeySystem, MockCDM::supportsKeySystemAndMimeType);
2056 }
2057 #endif
2058
2059 String Internals::markerTextForListItem(Element* element, ExceptionCode& ec)
2060 {
2061     if (!element) {
2062         ec = INVALID_ACCESS_ERR;
2063         return String();
2064     }
2065     return WebCore::markerTextForListItem(element);
2066 }
2067
2068 String Internals::getImageSourceURL(Element* element, ExceptionCode& ec)
2069 {
2070     if (!element) {
2071         ec = INVALID_ACCESS_ERR;
2072         return String();
2073     }
2074     return element->imageSourceURL();
2075 }
2076
2077 #if ENABLE(VIDEO)
2078 void Internals::simulateAudioInterruption(Node* node)
2079 {
2080 #if USE(GSTREAMER)
2081     HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2082     element->player()->simulateAudioInterruption();
2083 #else
2084     UNUSED_PARAM(node);
2085 #endif
2086 }
2087
2088 bool Internals::mediaElementHasCharacteristic(Node* node, const String& characteristic, ExceptionCode& ec)
2089 {
2090     if (!is<HTMLMediaElement>(*node))
2091         return false;
2092
2093     HTMLMediaElement* element = downcast<HTMLMediaElement>(node);
2094
2095     if (equalIgnoringCase(characteristic, "Audible"))
2096         return element->hasAudio();
2097     if (equalIgnoringCase(characteristic, "Visual"))
2098         return element->hasVideo();
2099     if (equalIgnoringCase(characteristic, "Legible"))
2100         return element->hasClosedCaptions();
2101
2102     ec = SYNTAX_ERR;
2103     return false;
2104 }
2105 #endif
2106
2107 bool Internals::isSelectPopupVisible(Node* node)
2108 {
2109     if (!is<HTMLSelectElement>(*node))
2110         return false;
2111
2112     HTMLSelectElement& select = downcast<HTMLSelectElement>(*node);
2113
2114     auto* renderer = select.renderer();
2115     ASSERT(renderer);
2116     if (!is<RenderMenuList>(*renderer))
2117         return false;
2118
2119 #if !PLATFORM(IOS)
2120     return downcast<RenderMenuList>(*renderer).popupIsVisible();
2121 #else
2122     return false;
2123 #endif // !PLATFORM(IOS)
2124 }
2125
2126 String Internals::captionsStyleSheetOverride(ExceptionCode& ec)
2127 {
2128     Document* document = contextDocument();
2129     if (!document || !document->page()) {
2130         ec = INVALID_ACCESS_ERR;
2131         return emptyString();
2132     }
2133
2134 #if ENABLE(VIDEO_TRACK)
2135     return document->page()->group().captionPreferences()->captionsStyleSheetOverride();
2136 #else
2137     return emptyString();
2138 #endif
2139 }
2140
2141 void Internals::setCaptionsStyleSheetOverride(const String& override, ExceptionCode& ec)
2142 {
2143     Document* document = contextDocument();
2144     if (!document || !document->page()) {
2145         ec = INVALID_ACCESS_ERR;
2146         return;
2147     }
2148
2149 #if ENABLE(VIDEO_TRACK)
2150     document->page()->group().captionPreferences()->setCaptionsStyleSheetOverride(override);
2151 #else
2152     UNUSED_PARAM(override);
2153 #endif
2154 }
2155
2156 void Internals::setPrimaryAudioTrackLanguageOverride(const String& language, ExceptionCode& ec)
2157 {
2158     Document* document = contextDocument();
2159     if (!document || !document->page()) {
2160         ec = INVALID_ACCESS_ERR;
2161         return;
2162     }
2163
2164 #if ENABLE(VIDEO_TRACK)
2165     document->page()->group().captionPreferences()->setPrimaryAudioTrackLanguageOverride(language);
2166 #else
2167     UNUSED_PARAM(language);
2168 #endif
2169 }
2170
2171 void Internals::setCaptionDisplayMode(const String& mode, ExceptionCode& ec)
2172 {
2173     Document* document = contextDocument();
2174     if (!document || !document->page()) {
2175         ec = INVALID_ACCESS_ERR;
2176         return;
2177     }
2178     
2179 #if ENABLE(VIDEO_TRACK)
2180     CaptionUserPreferences* captionPreferences = document->page()->group().captionPreferences();
2181     
2182     if (equalIgnoringCase(mode, "Automatic"))
2183         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::Automatic);
2184     else if (equalIgnoringCase(mode, "ForcedOnly"))
2185         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::ForcedOnly);
2186     else if (equalIgnoringCase(mode, "AlwaysOn"))
2187         captionPreferences->setCaptionDisplayMode(CaptionUserPreferences::AlwaysOn);
2188     else
2189         ec = SYNTAX_ERR;
2190 #else
2191     UNUSED_PARAM(mode);
2192 #endif
2193 }
2194
2195 #if ENABLE(VIDEO)
2196 PassRefPtr<TimeRanges> Internals::createTimeRanges(Float32Array* startTimes, Float32Array* endTimes)
2197 {
2198     ASSERT(startTimes && endTimes);
2199     ASSERT(startTimes->length() == endTimes->length());
2200     RefPtr<TimeRanges> ranges = TimeRanges::create();
2201
2202     unsigned count = std::min(startTimes->length(), endTimes->length());
2203     for (unsigned i = 0; i < count; ++i)
2204         ranges->add(startTimes->item(i), endTimes->item(i));
2205     return ranges;
2206 }
2207
2208 double Internals::closestTimeToTimeRanges(double time, TimeRanges* ranges)
2209 {
2210     return ranges->nearest(time);
2211 }
2212 #endif
2213
2214 PassRefPtr<ClientRect> Internals::selectionBounds(ExceptionCode& ec)
2215 {
2216     Document* document = contextDocument();
2217     if (!document || !document->frame()) {
2218         ec = INVALID_ACCESS_ERR;
2219         return ClientRect::create();
2220     }
2221
2222     return ClientRect::create(document->frame()->selection().selectionBounds());
2223 }
2224
2225 #if ENABLE(VIBRATION)
2226 bool Internals::isVibrating()
2227 {
2228     Page* page = contextDocument()->page();
2229     ASSERT(page);
2230
2231     return Vibration::from(page)->isVibrating();
2232 }
2233 #endif
2234
2235 bool Internals::isPluginUnavailabilityIndicatorObscured(Element* element, ExceptionCode& ec)
2236 {
2237     if (!element) {
2238         ec = INVALID_ACCESS_ERR;
2239         return false;
2240     }
2241
2242     auto* renderer = element->renderer();
2243     if (!is<RenderEmbeddedObject>(renderer)) {
2244         ec = INVALID_ACCESS_ERR;
2245         return false;
2246     }
2247
2248     return downcast<RenderEmbeddedObject>(*renderer).isReplacementObscured();
2249 }
2250     
2251 bool Internals::isPluginSnapshotted(Element* element, ExceptionCode& ec)
2252 {
2253     if (!element) {
2254         ec = INVALID_ACCESS_ERR;
2255         return false;
2256     }
2257     HTMLPlugInElement* pluginElement = downcast<HTMLPlugInElement>(element);
2258     return pluginElement->displayState() <= HTMLPlugInElement::DisplayingSnapshot;
2259 }
2260     
2261 #if ENABLE(MEDIA_SOURCE)
2262 void Internals::initializeMockMediaSource()
2263 {
2264 #if USE(AVFOUNDATION)
2265     WebCore::Settings::setAVFoundationEnabled(false);
2266 #endif
2267     MediaPlayerFactorySupport::callRegisterMediaEngine(MockMediaPlayerMediaSource::registerMediaEngine);
2268 }
2269
2270 Vector<String> Internals::bufferedSamplesForTrackID(SourceBuffer* buffer, const AtomicString& trackID)
2271 {
2272     if (!buffer)
2273         return Vector<String>();
2274
2275     return buffer->bufferedSamplesForTrackID(trackID);
2276 }
2277 #endif
2278
2279 #if ENABLE(VIDEO)
2280 void Internals::beginMediaSessionInterruption()
2281 {
2282     MediaSessionManager::sharedManager().beginInterruption(MediaSession::SystemInterruption);
2283 }
2284
2285 void Internals::endMediaSessionInterruption(const String& flagsString)
2286 {
2287     MediaSession::EndInterruptionFlags flags = MediaSession::NoFlags;
2288
2289     if (equalIgnoringCase(flagsString, "MayResumePlaying"))
2290         flags = MediaSession::MayResumePlaying;
2291     
2292     MediaSessionManager::sharedManager().endInterruption(flags);
2293 }
2294
2295 void Internals::applicationWillEnterForeground() const
2296 {
2297     MediaSessionManager::sharedManager().applicationWillEnterForeground();
2298 }
2299
2300 void Internals::applicationWillEnterBackground() const
2301 {
2302     MediaSessionManager::sharedManager().applicationWillEnterBackground();
2303 }
2304
2305 void Internals::setMediaSessionRestrictions(const String& mediaTypeString, const String& restrictionsString, ExceptionCode& ec)
2306 {
2307     MediaSession::MediaType mediaType = MediaSession::None;
2308     if (equalIgnoringCase(mediaTypeString, "Video"))
2309         mediaType = MediaSession::Video;
2310     else if (equalIgnoringCase(mediaTypeString, "Audio"))
2311         mediaType = MediaSession::Audio;
2312     else if (equalIgnoringCase(mediaTypeString, "WebAudio"))
2313         mediaType = MediaSession::WebAudio;
2314     else {
2315         ec = INVALID_ACCESS_ERR;
2316         return;
2317     }
2318
2319     MediaSessionManager::SessionRestrictions restrictions = MediaSessionManager::sharedManager().restrictions(mediaType);
2320     MediaSessionManager::sharedManager().removeRestriction(mediaType, restrictions);
2321
2322     restrictions = MediaSessionManager::NoRestrictions;
2323     
2324     if (equalIgnoringCase(restrictionsString, "ConcurrentPlaybackNotPermitted"))
2325         restrictions = MediaSessionManager::ConcurrentPlaybackNotPermitted;
2326     if (equalIgnoringCase(restrictionsString, "InlineVideoPlaybackRestricted"))
2327         restrictions += MediaSessionManager::InlineVideoPlaybackRestricted;
2328     if (equalIgnoringCase(restrictionsString, "MetadataPreloadingNotPermitted"))
2329         restrictions += MediaSessionManager::MetadataPreloadingNotPermitted;
2330     if (equalIgnoringCase(restrictionsString, "AutoPreloadingNotPermitted"))
2331         restrictions += MediaSessionManager::AutoPreloadingNotPermitted;
2332     if (equalIgnoringCase(restrictionsString, "BackgroundPlaybackNotPermitted"))
2333         restrictions += MediaSessionManager::BackgroundPlaybackNotPermitted;
2334
2335     MediaSessionManager::sharedManager().addRestriction(mediaType, restrictions);
2336 }
2337     
2338 void Internals::postRemoteControlCommand(const String& commandString, ExceptionCode& ec)
2339 {
2340     MediaSession::RemoteControlCommandType command;
2341     
2342     if (equalIgnoringCase(commandString, "Play"))
2343         command = MediaSession::PlayCommand;
2344     else if (equalIgnoringCase(commandString, "Pause"))
2345         command = MediaSession::PauseCommand;
2346     else if (equalIgnoringCase(commandString, "Stop"))
2347         command = MediaSession::StopCommand;
2348     else if (equalIgnoringCase(commandString, "TogglePlayPause"))
2349         command = MediaSession::TogglePlayPauseCommand;
2350     else if (equalIgnoringCase(commandString, "BeginSeekingBackward"))
2351         command = MediaSession::BeginSeekingBackwardCommand;
2352     else if (equalIgnoringCase(commandString, "EndSeekingBackward"))
2353         command = MediaSession::EndSeekingBackwardCommand;
2354     else if (equalIgnoringCase(commandString, "BeginSeekingForward"))
2355         command = MediaSession::BeginSeekingForwardCommand;
2356     else if (equalIgnoringCase(commandString, "EndSeekingForward"))
2357         command = MediaSession::EndSeekingForwardCommand;
2358     else {
2359         ec = INVALID_ACCESS_ERR;
2360         return;
2361     }
2362     
2363     MediaSessionManager::sharedManager().didReceiveRemoteControlCommand(command);
2364 }
2365 #endif // ENABLE(VIDEO)
2366
2367 void Internals::simulateSystemSleep() const
2368 {
2369 #if ENABLE(VIDEO)
2370     MediaSessionManager::sharedManager().systemWillSleep();
2371 #endif
2372 }
2373
2374 void Internals::simulateSystemWake() const
2375 {
2376 #if ENABLE(VIDEO)
2377     MediaSessionManager::sharedManager().systemDidWake();
2378 #endif
2379 }
2380
2381 void Internals::installMockPageOverlay(const String& overlayType, ExceptionCode& ec)
2382 {
2383     Document* document = contextDocument();
2384     if (!document || !document->frame()) {
2385         ec = INVALID_ACCESS_ERR;
2386         return;
2387     }
2388
2389     MockPageOverlayClient::shared().installOverlay(document->frame()->mainFrame(), overlayType == "view" ? PageOverlay::OverlayType::View : PageOverlay::OverlayType::Document);
2390 }
2391
2392 String Internals::pageOverlayLayerTreeAsText(ExceptionCode& ec) const
2393 {
2394     Document* document = contextDocument();
2395     if (!document || !document->frame()) {
2396         ec = INVALID_ACCESS_ERR;
2397         return String();
2398     }
2399
2400     document->updateLayout();
2401
2402     return MockPageOverlayClient::shared().layerTreeAsText(document->frame()->mainFrame());
2403 }
2404
2405 }