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