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