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