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