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