/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/testing/Internals.h"

#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptFunction.h"
#include "bindings/core/v8/ScriptPromise.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "bindings/core/v8/SerializedScriptValue.h"
#include "bindings/core/v8/SerializedScriptValueFactory.h"
#include "bindings/core/v8/V8IteratorResultValue.h"
#include "bindings/core/v8/V8ThrowException.h"
#include "core/HTMLNames.h"
#include "core/SVGNames.h"
#include "core/animation/AnimationTimeline.h"
#include "core/css/StyleSheetContents.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/css/resolver/StyleResolverStats.h"
#include "core/css/resolver/ViewportStyleResolver.h"
#include "core/dom/ClientRect.h"
#include "core/dom/ClientRectList.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/DOMNodeIds.h"
#include "core/dom/DOMPoint.h"
#include "core/dom/DOMStringList.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/Iterator.h"
#include "core/dom/NodeComputedStyle.h"
#include "core/dom/PseudoElement.h"
#include "core/dom/Range.h"
#include "core/dom/StaticNodeList.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/TreeScope.h"
#include "core/dom/ViewportDescription.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/FlatTreeTraversal.h"
#include "core/dom/shadow/SelectRuleFeatureSet.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/Editor.h"
#include "core/editing/PlainTextRange.h"
#include "core/editing/SurroundingText.h"
#include "core/editing/iterators/TextIterator.h"
#include "core/editing/markers/DocumentMarker.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/editing/serializers/Serialization.h"
#include "core/editing/spellcheck/SpellCheckRequester.h"
#include "core/editing/spellcheck/SpellChecker.h"
#include "core/fetch/MemoryCache.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/frame/EventHandlerRegistry.h"
#include "core/frame/FrameConsole.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLContentElement.h"
#include "core/html/HTMLIFrameElement.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLMediaElement.h"
#include "core/html/HTMLSelectElement.h"
#include "core/html/HTMLTextAreaElement.h"
#include "core/html/canvas/CanvasFontCache.h"
#include "core/html/canvas/CanvasRenderingContext.h"
#include "core/html/forms/FormController.h"
#include "core/html/shadow/ShadowElementNames.h"
#include "core/html/shadow/TextControlInnerElements.h"
#include "core/input/EventHandler.h"
#include "core/inspector/ConsoleMessageStorage.h"
#include "core/inspector/InspectorConsoleAgent.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/InstanceCounters.h"
#include "core/layout/LayoutMenuList.h"
#include "core/layout/LayoutObject.h"
#include "core/layout/LayoutTreeAsText.h"
#include "core/layout/api/LayoutMenuListItem.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/layout/compositing/CompositedLayerMapping.h"
#include "core/layout/compositing/PaintLayerCompositor.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/HistoryItem.h"
#include "core/page/ChromeClient.h"
#include "core/page/FocusController.h"
#include "core/page/NetworkStateNotifier.h"
#include "core/page/Page.h"
#include "core/page/PrintContext.h"
#include "core/page/scrolling/ScrollState.h"
#include "core/paint/PaintLayer.h"
#include "core/svg/SVGImageElement.h"
#include "core/testing/DictionaryTest.h"
#include "core/testing/GCObservation.h"
#include "core/testing/InternalRuntimeFlags.h"
#include "core/testing/InternalSettings.h"
#include "core/testing/LayerRect.h"
#include "core/testing/LayerRectList.h"
#include "core/testing/MockHyphenation.h"
#include "core/testing/PrivateScriptTest.h"
#include "core/testing/TypeConversions.h"
#include "core/testing/UnionTypesTest.h"
#include "core/workers/WorkerThread.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "platform/Cursor.h"
#include "platform/Language.h"
#include "platform/PlatformKeyboardEvent.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/TraceEvent.h"
#include "platform/geometry/IntRect.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/heap/Handle.h"
#include "platform/inspector_protocol/FrontendChannel.h"
#include "platform/scroll/ProgrammaticScrollAnimator.h"
#include "platform/weborigin/SchemeRegistry.h"
#include "public/platform/Platform.h"
#include "public/platform/WebConnectionType.h"
#include "public/platform/WebGraphicsContext3DProvider.h"
#include "public/platform/WebLayer.h"
#include "wtf/InstanceCounter.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/dtoa.h"
#include "wtf/text/StringBuffer.h"
#include <deque>
#include <v8.h>

namespace blink {

namespace {

class InternalsIterationSource final : public ValueIterable<int>::IterationSource {
public:
    bool next(ScriptState* scriptState, int& value, ExceptionState& exceptionState) override
    {
        if (m_index >= 5)
            return false;
        value = m_index * m_index;
        return true;
    }
};

} // namespace

static bool markerTypesFrom(const String& markerType, DocumentMarker::MarkerTypes& result)
{
    if (markerType.isEmpty() || equalIgnoringCase(markerType, "all"))
        result = DocumentMarker::AllMarkers();
    else if (equalIgnoringCase(markerType, "Spelling"))
        result =  DocumentMarker::Spelling;
    else if (equalIgnoringCase(markerType, "Grammar"))
        result =  DocumentMarker::Grammar;
    else if (equalIgnoringCase(markerType, "TextMatch"))
        result =  DocumentMarker::TextMatch;
    else
        return false;

    return true;
}

static SpellCheckRequester* spellCheckRequester(Document* document)
{
    if (!document || !document->frame())
        return 0;
    return &document->frame()->spellChecker().spellCheckRequester();
}

static ScrollableArea* scrollableAreaForNode(Node* node)
{
    if (!node)
        return nullptr;

    if (node->isDocumentNode()) {
        // This can be removed after root layer scrolling is enabled.
        if (FrameView* frameView = toDocument(node)->view())
            return frameView->layoutViewportScrollableArea();
    }

    LayoutObject* layoutObject = node->layoutObject();
    if (!layoutObject || !layoutObject->isBox())
        return nullptr;

    return toLayoutBox(layoutObject)->getScrollableArea();
}

const char* Internals::internalsId = "internals";

Internals* Internals::create(ScriptState* scriptState)
{
    return new Internals(scriptState);
}

Internals::~Internals()
{
}

static RuntimeEnabledFeatures::Backup* sFeaturesBackup = nullptr;

void Internals::resetToConsistentState(Page* page)
{
    ASSERT(page);

    if (!sFeaturesBackup)
        sFeaturesBackup = new RuntimeEnabledFeatures::Backup;
    sFeaturesBackup->restore();
    page->setIsCursorVisible(true);
    page->setPageScaleFactor(1);
    page->deprecatedLocalMainFrame()->view()->layoutViewportScrollableArea()->setScrollPosition(IntPoint(0, 0), ProgrammaticScroll);
    overrideUserPreferredLanguages(Vector<AtomicString>());
    if (!page->deprecatedLocalMainFrame()->spellChecker().isContinuousSpellCheckingEnabled())
        page->deprecatedLocalMainFrame()->spellChecker().toggleContinuousSpellChecking();
    if (page->deprecatedLocalMainFrame()->editor().isOverwriteModeEnabled())
        page->deprecatedLocalMainFrame()->editor().toggleOverwriteModeEnabled();

    if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
        scrollingCoordinator->reset();

    page->deprecatedLocalMainFrame()->view()->clear();
    PlatformKeyboardEvent::setCurrentCapsLockState(PlatformKeyboardEvent::OverrideCapsLockState::Default);
}

Internals::Internals(ScriptState* scriptState)
    : ContextLifecycleObserver(scriptState->getExecutionContext())
    , m_runtimeFlags(InternalRuntimeFlags::create())
{
}

Document* Internals::contextDocument() const
{
    return toDocument(getExecutionContext());
}

LocalFrame* Internals::frame() const
{
    if (!contextDocument())
        return 0;
    return contextDocument()->frame();
}

InternalSettings* Internals::settings() const
{
    Document* document = contextDocument();
    if (!document)
        return 0;
    Page* page = document->page();
    if (!page)
        return 0;
    return InternalSettings::from(*page);
}

InternalRuntimeFlags* Internals::runtimeFlags() const
{
    return m_runtimeFlags.get();
}

unsigned Internals::workerThreadCount() const
{
    return WorkerThread::workerThreadCount();
}

String Internals::address(Node* node)
{
    char buf[32];
    sprintf(buf, "%p", node);

    return String(buf);
}

GCObservation* Internals::observeGC(ScriptValue scriptValue)
{
    v8::Local<v8::Value> observedValue = scriptValue.v8Value();
    ASSERT(!observedValue.IsEmpty());
    if (observedValue->IsNull() || observedValue->IsUndefined()) {
        V8ThrowException::throwTypeError(v8::Isolate::GetCurrent(), "value to observe is null or undefined");
        return nullptr;
    }

    return GCObservation::create(observedValue);
}

unsigned Internals::updateStyleAndReturnAffectedElementCount(ExceptionState& exceptionState) const
{
    Document* document = contextDocument();
    if (!document) {
        exceptionState.throwDOMException(InvalidAccessError, "No context document is available.");
        return 0;
    }

    unsigned beforeCount = document->styleEngine().styleForElementCount();
    document->updateStyleAndLayoutTree();
    return document->styleEngine().styleForElementCount() - beforeCount;
}

unsigned Internals::needsLayoutCount(ExceptionState& exceptionState) const
{
    LocalFrame* contextFrame = frame();
    if (!contextFrame) {
        exceptionState.throwDOMException(InvalidAccessError, "No context frame is available.");
        return 0;
    }

    bool isPartial;
    unsigned needsLayoutObjects;
    unsigned totalObjects;
    contextFrame->view()->countObjectsNeedingLayout(needsLayoutObjects, totalObjects, isPartial);
    return needsLayoutObjects;
}

unsigned Internals::hitTestCount(Document* doc, ExceptionState& exceptionState) const
{
    if (!doc) {
        exceptionState.throwDOMException(InvalidAccessError, "Must supply document to check");
        return 0;
    }

    return doc->layoutViewItem().hitTestCount();
}

unsigned Internals::hitTestCacheHits(Document* doc, ExceptionState& exceptionState) const
{
    if (!doc) {
        exceptionState.throwDOMException(InvalidAccessError, "Must supply document to check");
        return 0;
    }

    return doc->layoutViewItem().hitTestCacheHits();
}

Element* Internals::elementFromPoint(Document* doc, double x, double y, bool ignoreClipping, bool allowChildFrameContent, ExceptionState& exceptionState) const
{
    if (!doc) {
        exceptionState.throwDOMException(InvalidAccessError, "Must supply document to check");
        return 0;
    }

    if (doc->layoutViewItem().isNull())
        return 0;

    HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active;
    if (ignoreClipping)
        hitType |= HitTestRequest::IgnoreClipping;
    if (allowChildFrameContent)
        hitType |= HitTestRequest::AllowChildFrameContent;

    HitTestRequest request(hitType);

    return doc->hitTestPoint(x, y, request);
}

void Internals::clearHitTestCache(Document* doc, ExceptionState& exceptionState) const
{
    if (!doc) {
        exceptionState.throwDOMException(InvalidAccessError, "Must supply document to check");
        return;
    }

    if (doc->layoutViewItem().isNull())
        return;

    doc->layoutViewItem().clearHitTestCache();
}

bool Internals::isPreloaded(const String& url)
{
    return isPreloadedBy(url, contextDocument());
}

bool Internals::isPreloadedBy(const String& url, Document* document)
{
    if (!document)
        return false;
    return document->fetcher()->isPreloaded(document->completeURL(url));
}

bool Internals::isLoadingFromMemoryCache(const String& url)
{
    if (!contextDocument())
        return false;
    const String cacheIdentifier = contextDocument()->fetcher()->getCacheIdentifier();
    Resource* resource = memoryCache()->resourceForURL(contextDocument()->completeURL(url), cacheIdentifier);
    return resource && resource->getStatus() == Resource::Cached;
}

bool Internals::isSharingStyle(Element* element1, Element* element2) const
{
    ASSERT(element1 && element2);
    return element1->computedStyle() == element2->computedStyle();
}

bool Internals::isValidContentSelect(Element* insertionPoint, ExceptionState& exceptionState)
{
    ASSERT(insertionPoint);
    if (!insertionPoint->isInsertionPoint()) {
        exceptionState.throwDOMException(InvalidAccessError, "The element is not an insertion point.");
        return false;
    }

    return isHTMLContentElement(*insertionPoint) && toHTMLContentElement(*insertionPoint).isSelectValid();
}

Node* Internals::treeScopeRootNode(Node* node)
{
    ASSERT(node);
    return &node->treeScope().rootNode();
}

Node* Internals::parentTreeScope(Node* node)
{
    ASSERT(node);
    const TreeScope* parentTreeScope = node->treeScope().parentTreeScope();
    return parentTreeScope ? &parentTreeScope->rootNode() : 0;
}

bool Internals::hasSelectorForIdInShadow(Element* host, const AtomicString& idValue, ExceptionState& exceptionState)
{
    ASSERT(host);
    if (!host->shadow()) {
        exceptionState.throwDOMException(InvalidAccessError, "The host element does not have a shadow.");
        return false;
    }

    return host->shadow()->ensureSelectFeatureSet().hasSelectorForId(idValue);
}

bool Internals::hasSelectorForClassInShadow(Element* host, const AtomicString& className, ExceptionState& exceptionState)
{
    ASSERT(host);
    if (!host->shadow()) {
        exceptionState.throwDOMException(InvalidAccessError, "The host element does not have a shadow.");
        return false;
    }

    return host->shadow()->ensureSelectFeatureSet().hasSelectorForClass(className);
}

bool Internals::hasSelectorForAttributeInShadow(Element* host, const AtomicString& attributeName, ExceptionState& exceptionState)
{
    ASSERT(host);
    if (!host->shadow()) {
        exceptionState.throwDOMException(InvalidAccessError, "The host element does not have a shadow.");
        return false;
    }

    return host->shadow()->ensureSelectFeatureSet().hasSelectorForAttribute(attributeName);
}

unsigned short Internals::compareTreeScopePosition(const Node* node1, const Node* node2, ExceptionState& exceptionState) const
{
    ASSERT(node1 && node2);
    const TreeScope* treeScope1 = node1->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node1)) :
        node1->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node1)) : 0;
    const TreeScope* treeScope2 = node2->isDocumentNode() ? static_cast<const TreeScope*>(toDocument(node2)) :
        node2->isShadowRoot() ? static_cast<const TreeScope*>(toShadowRoot(node2)) : 0;
    if (!treeScope1 || !treeScope2) {
        exceptionState.throwDOMException(InvalidAccessError, String::format("The %s node is neither a document node, nor a shadow root.", treeScope1 ? "second" : "first"));
        return 0;
    }
    return treeScope1->comparePosition(*treeScope2);
}

void Internals::pauseAnimations(double pauseTime, ExceptionState& exceptionState)
{
    if (pauseTime < 0) {
        exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexExceedsMinimumBound("pauseTime", pauseTime, 0.0));
        return;
    }

    frame()->view()->updateAllLifecyclePhases();
    frame()->document()->timeline().pauseAnimationsForTesting(pauseTime);
}

bool Internals::isCompositedAnimation(Animation* animation)
{
    return animation->hasActiveAnimationsOnCompositor();
}

void Internals::disableCompositedAnimation(Animation* animation)
{
    animation->disableCompositedAnimationForTesting();
}

void Internals::disableCSSAdditiveAnimations()
{
    RuntimeEnabledFeatures::setCSSAdditiveAnimationsEnabled(false);
}

void Internals::advanceTimeForImage(Element* image, double deltaTimeInSeconds, ExceptionState& exceptionState)
{
    ASSERT(image);
    if (deltaTimeInSeconds < 0) {
        exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::indexExceedsMinimumBound("deltaTimeInSeconds", deltaTimeInSeconds, 0.0));
        return;
    }

    ImageResource* resource = nullptr;
    if (isHTMLImageElement(*image)) {
        resource = toHTMLImageElement(*image).cachedImage();
    } else if (isSVGImageElement(*image)) {
        resource = toSVGImageElement(*image).cachedImage();
    } else {
        exceptionState.throwDOMException(InvalidAccessError, "The element provided is not a image element.");
        return;
    }

    if (!resource || !resource->hasImage()) {
        exceptionState.throwDOMException(InvalidAccessError, "The image resource is not available.");
        return;
    }

    Image* imageData = resource->getImage();
    if (!imageData->isBitmapImage()) {
        exceptionState.throwDOMException(InvalidAccessError, "The image resource is not a BitmapImage type.");
        return;
    }

    imageData->advanceTime(deltaTimeInSeconds);
}

void Internals::advanceImageAnimation(Element* image, ExceptionState& exceptionState)
{
    ASSERT(image);

    ImageResource* resource = nullptr;
    if (isHTMLImageElement(*image)) {
        resource = toHTMLImageElement(*image).cachedImage();
    } else if (isSVGImageElement(*image)) {
        resource = toSVGImageElement(*image).cachedImage();
    } else {
        exceptionState.throwDOMException(InvalidAccessError, "The element provided is not a image element.");
        return;
    }

    if (!resource || !resource->hasImage()) {
        exceptionState.throwDOMException(InvalidAccessError, "The image resource is not available.");
        return;
    }

    Image* imageData = resource->getImage();
    imageData->advanceAnimationForTesting();
}

bool Internals::hasShadowInsertionPoint(const Node* root, ExceptionState& exceptionState) const
{
    ASSERT(root);
    if (!root->isShadowRoot()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node argument is not a shadow root.");
        return false;
    }
    return toShadowRoot(root)->containsShadowElements();
}

bool Internals::hasContentElement(const Node* root, ExceptionState& exceptionState) const
{
    ASSERT(root);
    if (!root->isShadowRoot()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node argument is not a shadow root.");
        return false;
    }
    return toShadowRoot(root)->containsContentElements();
}

size_t Internals::countElementShadow(const Node* root, ExceptionState& exceptionState) const
{
    ASSERT(root);
    if (!root->isShadowRoot()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node argument is not a shadow root.");
        return 0;
    }
    return toShadowRoot(root)->childShadowRootCount();
}

Node* Internals::nextSiblingInFlatTree(Node* node, ExceptionState& exceptionState)
{
    ASSERT(node);
    if (!node->canParticipateInFlatTree()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the flat tree.");
        return 0;
    }
    return FlatTreeTraversal::nextSibling(*node);
}

Node* Internals::firstChildInFlatTree(Node* node, ExceptionState& exceptionState)
{
    ASSERT(node);
    if (!node->canParticipateInFlatTree()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the flat tree");
        return 0;
    }
    return FlatTreeTraversal::firstChild(*node);
}

Node* Internals::lastChildInFlatTree(Node* node, ExceptionState& exceptionState)
{
    ASSERT(node);
    if (!node->canParticipateInFlatTree()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the flat tree.");
        return 0;
    }
    return FlatTreeTraversal::lastChild(*node);
}

Node* Internals::nextInFlatTree(Node* node, ExceptionState& exceptionState)
{
    ASSERT(node);
    if (!node->canParticipateInFlatTree()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the flat tree.");
        return 0;
    }
    return FlatTreeTraversal::next(*node);
}

Node* Internals::previousInFlatTree(Node* node, ExceptionState& exceptionState)
{
    ASSERT(node);
    if (!node->canParticipateInFlatTree()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node argument doesn't particite in the flat tree.");
        return 0;
    }
    return FlatTreeTraversal::previous(*node);
}

String Internals::elementLayoutTreeAsText(Element* element, ExceptionState& exceptionState)
{
    ASSERT(element);
    String representation = externalRepresentation(element);
    if (representation.isEmpty()) {
        exceptionState.throwDOMException(InvalidAccessError, "The element provided has no external representation.");
        return String();
    }

    return representation;
}

CSSStyleDeclaration* Internals::computedStyleIncludingVisitedInfo(Node* node) const
{
    ASSERT(node);
    bool allowVisitedStyle = true;
    return CSSComputedStyleDeclaration::create(node, allowVisitedStyle);
}

ShadowRoot* Internals::createUserAgentShadowRoot(Element* host)
{
    ASSERT(host);
    return &host->ensureUserAgentShadowRoot();
}

ShadowRoot* Internals::shadowRoot(Element* host)
{
    // FIXME: Internals::shadowRoot() in tests should be converted to youngestShadowRoot() or oldestShadowRoot().
    // https://bugs.webkit.org/show_bug.cgi?id=78465
    return youngestShadowRoot(host);
}

ShadowRoot* Internals::youngestShadowRoot(Element* host)
{
    ASSERT(host);
    if (ElementShadow* shadow = host->shadow())
        return &shadow->youngestShadowRoot();
    return 0;
}

ShadowRoot* Internals::oldestShadowRoot(Element* host)
{
    ASSERT(host);
    if (ElementShadow* shadow = host->shadow())
        return shadow->oldestShadowRoot();
    return 0;
}

ShadowRoot* Internals::youngerShadowRoot(Node* shadow, ExceptionState& exceptionState)
{
    ASSERT(shadow);
    if (!shadow->isShadowRoot()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node provided is not a shadow root.");
        return 0;
    }

    return toShadowRoot(shadow)->youngerShadowRoot();
}

String Internals::shadowRootType(const Node* root, ExceptionState& exceptionState) const
{
    ASSERT(root);
    if (!root->isShadowRoot()) {
        exceptionState.throwDOMException(InvalidAccessError, "The node provided is not a shadow root.");
        return String();
    }

    switch (toShadowRoot(root)->type()) {
    case ShadowRootType::UserAgent:
        return String("UserAgentShadowRoot");
    case ShadowRootType::V0:
        return String("V0ShadowRoot");
    case ShadowRootType::Open:
        return String("OpenShadowRoot");
    case ShadowRootType::Closed:
        return String("ClosedShadowRoot");
    default:
        ASSERT_NOT_REACHED();
        return String("Unknown");
    }
}

const AtomicString& Internals::shadowPseudoId(Element* element)
{
    ASSERT(element);
    return element->shadowPseudoId();
}

String Internals::visiblePlaceholder(Element* element)
{
    if (element && isHTMLTextFormControlElement(*element)) {
        const HTMLTextFormControlElement& textFormControlElement = toHTMLTextFormControlElement(*element);
        if (!textFormControlElement.isPlaceholderVisible())
            return String();
        if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
            return placeholderElement->textContent();
    }

    return String();
}

void Internals::selectColorInColorChooser(Element* element, const String& colorValue)
{
    ASSERT(element);
    if (!isHTMLInputElement(*element))
        return;
    Color color;
    if (!color.setFromString(colorValue))
        return;
    toHTMLInputElement(*element).selectColorInColorChooser(color);
}

void Internals::endColorChooser(Element* element)
{
    ASSERT(element);
    if (!isHTMLInputElement(*element))
        return;
    toHTMLInputElement(*element).endColorChooser();
}

bool Internals::hasAutofocusRequest(Document* document)
{
    if (!document)
        document = contextDocument();
    return document->autofocusElement();
}

bool Internals::hasAutofocusRequest()
{
    return hasAutofocusRequest(0);
}

Vector<String> Internals::formControlStateOfHistoryItem(ExceptionState& exceptionState)
{
    HistoryItem* mainItem = frame()->loader().currentItem();
    if (!mainItem) {
        exceptionState.throwDOMException(InvalidAccessError, "No history item is available.");
        return Vector<String>();
    }
    return mainItem->documentState();
}

void Internals::setFormControlStateOfHistoryItem(const Vector<String>& state, ExceptionState& exceptionState)
{
    HistoryItem* mainItem = frame()->loader().currentItem();
    if (!mainItem) {
        exceptionState.throwDOMException(InvalidAccessError, "No history item is available.");
        return;
    }
    mainItem->clearDocumentState();
    mainItem->setDocumentState(state);
}

DOMWindow* Internals::pagePopupWindow() const
{
    Document* document = contextDocument();
    if (!document)
        return nullptr;
    if (Page* page = document->page())
        return page->chromeClient().pagePopupWindowForTesting();
    return nullptr;
}

ClientRect* Internals::absoluteCaretBounds(ExceptionState& exceptionState)
{
    Document* document = contextDocument();
    if (!document || !document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "No context document can be obtained.");
        return ClientRect::create();
    }

    return ClientRect::create(document->frame()->selection().absoluteCaretBounds());
}

ClientRect* Internals::boundingBox(Element* element)
{
    ASSERT(element);

    element->document().updateStyleAndLayoutIgnorePendingStylesheets();
    LayoutObject* layoutObject = element->layoutObject();
    if (!layoutObject)
        return ClientRect::create();
    return ClientRect::create(layoutObject->absoluteBoundingBoxRectIgnoringTransforms());
}

unsigned Internals::markerCountForNode(Node* node, const String& markerType, ExceptionState& exceptionState)
{
    ASSERT(node);
    DocumentMarker::MarkerTypes markerTypes = 0;
    if (!markerTypesFrom(markerType, markerTypes)) {
        exceptionState.throwDOMException(SyntaxError, "The marker type provided ('" + markerType + "') is invalid.");
        return 0;
    }

    return node->document().markers().markersFor(node, markerTypes).size();
}

unsigned Internals::activeMarkerCountForNode(Node* node)
{
    ASSERT(node);

    // Only TextMatch markers can be active.
    DocumentMarker::MarkerType markerType = DocumentMarker::TextMatch;
    DocumentMarkerVector markers = node->document().markers().markersFor(node, markerType);

    unsigned activeMarkerCount = 0;
    for (const auto& marker : markers) {
        if (marker->activeMatch())
            activeMarkerCount++;
    }

    return activeMarkerCount;
}

DocumentMarker* Internals::markerAt(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
{
    ASSERT(node);
    DocumentMarker::MarkerTypes markerTypes = 0;
    if (!markerTypesFrom(markerType, markerTypes)) {
        exceptionState.throwDOMException(SyntaxError, "The marker type provided ('" + markerType + "') is invalid.");
        return 0;
    }

    DocumentMarkerVector markers = node->document().markers().markersFor(node, markerTypes);
    if (markers.size() <= index)
        return 0;
    return markers[index];
}

Range* Internals::markerRangeForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
{
    ASSERT(node);
    DocumentMarker* marker = markerAt(node, markerType, index, exceptionState);
    if (!marker)
        return nullptr;
    return Range::create(node->document(), node, marker->startOffset(), node, marker->endOffset());
}

String Internals::markerDescriptionForNode(Node* node, const String& markerType, unsigned index, ExceptionState& exceptionState)
{
    DocumentMarker* marker = markerAt(node, markerType, index, exceptionState);
    if (!marker)
        return String();
    return marker->description();
}

void Internals::addTextMatchMarker(const Range* range, bool isActive)
{
    ASSERT(range);
    range->ownerDocument().updateStyleAndLayoutIgnorePendingStylesheets();
    range->ownerDocument().markers().addTextMatchMarker(range, isActive);
}

void Internals::setMarkersActive(Node* node, unsigned startOffset, unsigned endOffset, bool active)
{
    ASSERT(node);
    node->document().markers().setMarkersActive(node, startOffset, endOffset, active);
}

void Internals::setMarkedTextMatchesAreHighlighted(Document* document, bool highlight)
{
    if (!document || !document->frame())
        return;

    document->frame()->editor().setMarkedTextMatchesAreHighlighted(highlight);
}

void Internals::setFrameViewPosition(Document* document, long x, long y, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->view()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return;
    }

    FrameView* frameView = document->view();
    bool scrollbarsSuppressedOldValue = frameView->scrollbarsSuppressed();

    frameView->setScrollbarsSuppressed(false);
    frameView->setScrollOffsetFromInternals(IntPoint(x, y));
    frameView->setScrollbarsSuppressed(scrollbarsSuppressedOldValue);
}

String Internals::viewportAsText(Document* document, float, int availableWidth, int availableHeight, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->page()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return String();
    }

    document->updateStyleAndLayoutIgnorePendingStylesheets();

    Page* page = document->page();

    // Update initial viewport size.
    IntSize initialViewportSize(availableWidth, availableHeight);
    document->page()->deprecatedLocalMainFrame()->view()->setFrameRect(IntRect(IntPoint::zero(), initialViewportSize));

    ViewportDescription description = page->viewportDescription();
    PageScaleConstraints constraints = description.resolve(FloatSize(initialViewportSize), Length());

    constraints.fitToContentsWidth(constraints.layoutSize.width(), availableWidth);
    constraints.resolveAutoInitialScale();

    StringBuilder builder;

    builder.appendLiteral("viewport size ");
    builder.append(String::number(constraints.layoutSize.width()));
    builder.append('x');
    builder.append(String::number(constraints.layoutSize.height()));

    builder.appendLiteral(" scale ");
    builder.append(String::number(constraints.initialScale));
    builder.appendLiteral(" with limits [");
    builder.append(String::number(constraints.minimumScale));
    builder.appendLiteral(", ");
    builder.append(String::number(constraints.maximumScale));

    builder.appendLiteral("] and userScalable ");
    builder.append(description.userZoom ? "true" : "false");

    return builder.toString();
}

bool Internals::elementShouldAutoComplete(Element* element, ExceptionState& exceptionState)
{
    ASSERT(element);
    if (isHTMLInputElement(*element))
        return toHTMLInputElement(*element).shouldAutocomplete();

    exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT.");
    return false;
}

String Internals::suggestedValue(Element* element, ExceptionState& exceptionState)
{
    ASSERT(element);
    if (!element->isFormControlElement()) {
        exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element.");
        return String();
    }

    String suggestedValue;
    if (isHTMLInputElement(*element))
        suggestedValue = toHTMLInputElement(*element).suggestedValue();

    if (isHTMLTextAreaElement(*element))
        suggestedValue = toHTMLTextAreaElement(*element).suggestedValue();

    if (isHTMLSelectElement(*element))
        suggestedValue = toHTMLSelectElement(*element).suggestedValue();

    return suggestedValue;
}

void Internals::setSuggestedValue(Element* element, const String& value, ExceptionState& exceptionState)
{
    ASSERT(element);
    if (!element->isFormControlElement()) {
        exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element.");
        return;
    }

    if (isHTMLInputElement(*element))
        toHTMLInputElement(*element).setSuggestedValue(value);

    if (isHTMLTextAreaElement(*element))
        toHTMLTextAreaElement(*element).setSuggestedValue(value);

    if (isHTMLSelectElement(*element))
        toHTMLSelectElement(*element).setSuggestedValue(value);
}

void Internals::setEditingValue(Element* element, const String& value, ExceptionState& exceptionState)
{
    ASSERT(element);
    if (!isHTMLInputElement(*element)) {
        exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT.");
        return;
    }

    toHTMLInputElement(*element).setEditingValue(value);
}

void Internals::setAutofilled(Element* element, bool enabled, ExceptionState& exceptionState)
{
    ASSERT(element);
    if (!element->isFormControlElement()) {
        exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not a form control element.");
        return;
    }
    toHTMLFormControlElement(element)->setAutofilled(enabled);
}

Range* Internals::rangeFromLocationAndLength(Element* scope, int rangeLocation, int rangeLength)
{
    ASSERT(scope);

    // TextIterator depends on Layout information, make sure layout it up to date.
    scope->document().updateStyleAndLayoutIgnorePendingStylesheets();

    return createRange(PlainTextRange(rangeLocation, rangeLocation + rangeLength).createRange(*scope));
}

unsigned Internals::locationFromRange(Element* scope, const Range* range)
{
    ASSERT(scope && range);
    // PlainTextRange depends on Layout information, make sure layout it up to date.
    scope->document().updateStyleAndLayoutIgnorePendingStylesheets();

    return PlainTextRange::create(*scope, *range).start();
}

unsigned Internals::lengthFromRange(Element* scope, const Range* range)
{
    ASSERT(scope && range);
    // PlainTextRange depends on Layout information, make sure layout it up to date.
    scope->document().updateStyleAndLayoutIgnorePendingStylesheets();

    return PlainTextRange::create(*scope, *range).length();
}

String Internals::rangeAsText(const Range* range)
{
    ASSERT(range);
    return range->text();
}

// FIXME: The next four functions are very similar - combine them once
// bestClickableNode/bestContextMenuNode have been combined..

DOMPoint* Internals::touchPositionAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return 0;
    }

    document->updateStyleAndLayout();

    IntSize radius(width / 2, height / 2);
    IntPoint point(x + radius.width(), y + radius.height());

    EventHandler& eventHandler = document->frame()->eventHandler();
    IntPoint hitTestPoint = document->frame()->view()->rootFrameToContents(point);
    HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased, LayoutSize(radius));

    Node* targetNode = 0;
    IntPoint adjustedPoint;

    bool foundNode = eventHandler.bestClickableNodeForHitTestResult(result, adjustedPoint, targetNode);
    if (foundNode)
        return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y());

    return 0;
}

Node* Internals::touchNodeAdjustedToBestClickableNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return 0;
    }

    document->updateStyleAndLayout();

    IntSize radius(width / 2, height / 2);
    IntPoint point(x + radius.width(), y + radius.height());

    EventHandler& eventHandler = document->frame()->eventHandler();
    IntPoint hitTestPoint = document->frame()->view()->rootFrameToContents(point);
    HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased, LayoutSize(radius));

    Node* targetNode = 0;
    IntPoint adjustedPoint;
    document->frame()->eventHandler().bestClickableNodeForHitTestResult(result, adjustedPoint, targetNode);
    return targetNode;
}

DOMPoint* Internals::touchPositionAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return 0;
    }

    document->updateStyleAndLayout();

    IntSize radius(width / 2, height / 2);
    IntPoint point(x + radius.width(), y + radius.height());

    EventHandler& eventHandler = document->frame()->eventHandler();
    IntPoint hitTestPoint = document->frame()->view()->rootFrameToContents(point);
    HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased, LayoutSize(radius));

    Node* targetNode = 0;
    IntPoint adjustedPoint;

    bool foundNode = eventHandler.bestContextMenuNodeForHitTestResult(result, adjustedPoint, targetNode);
    if (foundNode)
        return DOMPoint::create(adjustedPoint.x(), adjustedPoint.y());

    return DOMPoint::create(x, y);
}

Node* Internals::touchNodeAdjustedToBestContextMenuNode(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return 0;
    }

    document->updateStyleAndLayout();

    IntSize radius(width / 2, height / 2);
    IntPoint point(x + radius.width(), y + radius.height());

    EventHandler& eventHandler = document->frame()->eventHandler();
    IntPoint hitTestPoint = document->frame()->view()->rootFrameToContents(point);
    HitTestResult result = eventHandler.hitTestResultAtPoint(hitTestPoint, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased, LayoutSize(radius));

    Node* targetNode = 0;
    IntPoint adjustedPoint;
    eventHandler.bestContextMenuNodeForHitTestResult(result, adjustedPoint, targetNode);
    return targetNode;
}

ClientRect* Internals::bestZoomableAreaForTouchPoint(long x, long y, long width, long height, Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return nullptr;
    }

    document->updateStyleAndLayout();

    IntSize radius(width / 2, height / 2);
    IntPoint point(x + radius.width(), y + radius.height());

    Node* targetNode = 0;
    IntRect zoomableArea;
    bool foundNode = document->frame()->eventHandler().bestZoomableAreaForTouchPoint(point, radius, zoomableArea, targetNode);
    if (foundNode)
        return ClientRect::create(zoomableArea);

    return nullptr;
}


int Internals::lastSpellCheckRequestSequence(Document* document, ExceptionState& exceptionState)
{
    SpellCheckRequester* requester = spellCheckRequester(document);

    if (!requester) {
        exceptionState.throwDOMException(InvalidAccessError, "No spell check requestor can be obtained for the provided document.");
        return -1;
    }

    return requester->lastRequestSequence();
}

int Internals::lastSpellCheckProcessedSequence(Document* document, ExceptionState& exceptionState)
{
    SpellCheckRequester* requester = spellCheckRequester(document);

    if (!requester) {
        exceptionState.throwDOMException(InvalidAccessError, "No spell check requestor can be obtained for the provided document.");
        return -1;
    }

    return requester->lastProcessedSequence();
}

Vector<AtomicString> Internals::userPreferredLanguages() const
{
    return blink::userPreferredLanguages();
}

// Optimally, the bindings generator would pass a Vector<AtomicString> here but
// this is not supported yet.
void Internals::setUserPreferredLanguages(const Vector<String>& languages)
{
    Vector<AtomicString> atomicLanguages;
    for (size_t i = 0; i < languages.size(); ++i)
        atomicLanguages.append(AtomicString(languages[i]));
    overrideUserPreferredLanguages(atomicLanguages);
}

unsigned Internals::activeDOMObjectCount(Document* document)
{
    ASSERT(document);
    return document->activeDOMObjectCount();
}

static unsigned eventHandlerCount(Document& document, EventHandlerRegistry::EventHandlerClass handlerClass)
{
    if (!document.frameHost())
        return 0;
    EventHandlerRegistry* registry = &document.frameHost()->eventHandlerRegistry();
    unsigned count = 0;
    const EventTargetSet* targets = registry->eventHandlerTargets(handlerClass);
    if (targets) {
        for (const auto& target : *targets)
            count += target.value;
    }
    return count;
}

unsigned Internals::wheelEventHandlerCount(Document* document)
{
    ASSERT(document);
    return eventHandlerCount(*document, EventHandlerRegistry::WheelEventBlocking);
}

unsigned Internals::scrollEventHandlerCount(Document* document)
{
    ASSERT(document);
    return eventHandlerCount(*document, EventHandlerRegistry::ScrollEvent);
}

unsigned Internals::touchStartOrMoveEventHandlerCount(Document* document)
{
    ASSERT(document);
    return eventHandlerCount(*document, EventHandlerRegistry::TouchStartOrMoveEventBlocking) + eventHandlerCount(*document, EventHandlerRegistry::TouchStartOrMoveEventPassive);
}

unsigned Internals::touchEndOrCancelEventHandlerCount(Document* document)
{
    ASSERT(document);
    return eventHandlerCount(*document, EventHandlerRegistry::TouchEndOrCancelEventBlocking) + eventHandlerCount(*document, EventHandlerRegistry::TouchEndOrCancelEventPassive);
}

static PaintLayer* findLayerForGraphicsLayer(PaintLayer* searchRoot, GraphicsLayer* graphicsLayer, IntSize* layerOffset, String* layerType)
{
    *layerOffset = IntSize();
    if (searchRoot->hasCompositedLayerMapping() && graphicsLayer == searchRoot->compositedLayerMapping()->mainGraphicsLayer()) {
        // If the |graphicsLayer| sets the scrollingContent layer as its
        // scroll parent, consider it belongs to the scrolling layer and
        // mark the layer type as "scrolling".
        if (!searchRoot->layoutObject()->hasTransformRelatedProperty() && searchRoot->scrollParent() && searchRoot->parent() == searchRoot->scrollParent()) {
            *layerType = "scrolling";
            // For hit-test rect visualization to work, the hit-test rect should
            // be relative to the scrolling layer and in this case the hit-test
            // rect is relative to the element's own GraphicsLayer. So we will have
            // to adjust the rect to be relative to the scrolling layer here.
            // Only when the element's offsetParent == scroller's offsetParent we
            // can compute the element's relative position to the scrolling content
            // in this way.
            if (searchRoot->layoutObject()->offsetParent() == searchRoot->parent()->layoutObject()->offsetParent()) {
                LayoutBoxModelObject* current = searchRoot->layoutObject();
                LayoutBoxModelObject* parent = searchRoot->parent()->layoutObject();
                layerOffset->setWidth((parent->offsetLeft() - current->offsetLeft()).toInt());
                layerOffset->setHeight((parent->offsetTop() - current->offsetTop()).toInt());
                return searchRoot->parent();
            }
        }

        LayoutRect rect;
        PaintLayer::mapRectInPaintInvalidationContainerToBacking(*searchRoot->layoutObject(), rect);
        *layerOffset = IntSize(rect.x(), rect.y());
        return searchRoot;
    }

    // If the |graphicsLayer| is a scroller's scrollingContent layer,
    // consider this is a scrolling layer.
    GraphicsLayer* layerForScrolling = searchRoot->getScrollableArea() ? searchRoot->getScrollableArea()->layerForScrolling() : 0;
    if (graphicsLayer == layerForScrolling) {
        *layerType = "scrolling";
        return searchRoot;
    }

    if (searchRoot->compositingState() == PaintsIntoGroupedBacking) {
        GraphicsLayer* squashingLayer = searchRoot->groupedMapping()->squashingLayer();
        if (graphicsLayer == squashingLayer) {
            *layerType ="squashing";
            LayoutRect rect;
            PaintLayer::mapRectInPaintInvalidationContainerToBacking(*searchRoot->layoutObject(), rect);
            *layerOffset = IntSize(rect.x(), rect.y());
            return searchRoot;
        }
    }

    GraphicsLayer* layerForHorizontalScrollbar = searchRoot->getScrollableArea() ? searchRoot->getScrollableArea()->layerForHorizontalScrollbar() : 0;
    if (graphicsLayer == layerForHorizontalScrollbar) {
        *layerType = "horizontalScrollbar";
        return searchRoot;
    }

    GraphicsLayer* layerForVerticalScrollbar = searchRoot->getScrollableArea() ? searchRoot->getScrollableArea()->layerForVerticalScrollbar() : 0;
    if (graphicsLayer == layerForVerticalScrollbar) {
        *layerType = "verticalScrollbar";
        return searchRoot;
    }

    GraphicsLayer* layerForScrollCorner = searchRoot->getScrollableArea() ? searchRoot->getScrollableArea()->layerForScrollCorner() : 0;
    if (graphicsLayer == layerForScrollCorner) {
        *layerType = "scrollCorner";
        return searchRoot;
    }

    // Search right to left to increase the chances that we'll choose the top-most layers in a
    // grouped mapping for squashing.
    for (PaintLayer* child = searchRoot->lastChild(); child; child = child->previousSibling()) {
        PaintLayer* foundLayer = findLayerForGraphicsLayer(child, graphicsLayer, layerOffset, layerType);
        if (foundLayer)
            return foundLayer;
    }

    return 0;
}

// Given a vector of rects, merge those that are adjacent, leaving empty rects
// in the place of no longer used slots. This is intended to simplify the list
// of rects returned by an SkRegion (which have been split apart for sorting
// purposes). No attempt is made to do this efficiently (eg. by relying on the
// sort criteria of SkRegion).
static void mergeRects(WebVector<blink::WebRect>& rects)
{
    for (size_t i = 0; i < rects.size(); ++i) {
        if (rects[i].isEmpty())
            continue;
        bool updated;
        do {
            updated = false;
            for (size_t j = i+1; j < rects.size(); ++j) {
                if (rects[j].isEmpty())
                    continue;
                // Try to merge rects[j] into rects[i] along the 4 possible edges.
                if (rects[i].y == rects[j].y && rects[i].height == rects[j].height) {
                    if (rects[i].x + rects[i].width == rects[j].x) {
                        rects[i].width += rects[j].width;
                        rects[j] = blink::WebRect();
                        updated = true;
                    } else if (rects[i].x == rects[j].x + rects[j].width) {
                        rects[i].x = rects[j].x;
                        rects[i].width += rects[j].width;
                        rects[j] = blink::WebRect();
                        updated = true;
                    }
                } else if (rects[i].x == rects[j].x && rects[i].width == rects[j].width) {
                    if (rects[i].y + rects[i].height == rects[j].y) {
                        rects[i].height += rects[j].height;
                        rects[j] = blink::WebRect();
                        updated = true;
                    } else if (rects[i].y == rects[j].y + rects[j].height) {
                        rects[i].y = rects[j].y;
                        rects[i].height += rects[j].height;
                        rects[j] = blink::WebRect();
                        updated = true;
                    }
                }
            }
        } while (updated);
    }
}

static void accumulateLayerRectList(PaintLayerCompositor* compositor, GraphicsLayer* graphicsLayer, LayerRectList* rects)
{
    WebVector<blink::WebRect> layerRects = graphicsLayer->platformLayer()->touchEventHandlerRegion();
    if (!layerRects.isEmpty()) {
        mergeRects(layerRects);
        String layerType;
        IntSize layerOffset;
        PaintLayer* paintLayer = findLayerForGraphicsLayer(compositor->rootLayer(), graphicsLayer, &layerOffset, &layerType);
        Node* node = paintLayer ? paintLayer->layoutObject()->node() : 0;
        for (size_t i = 0; i < layerRects.size(); ++i) {
            if (!layerRects[i].isEmpty()) {
                rects->append(node, layerType, layerOffset.width(), layerOffset.height(), ClientRect::create(layerRects[i]));
            }
        }
    }

    size_t numChildren = graphicsLayer->children().size();
    for (size_t i = 0; i < numChildren; ++i)
        accumulateLayerRectList(compositor, graphicsLayer->children()[i], rects);
}

LayerRectList* Internals::touchEventTargetLayerRects(Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->view() || !document->page() || document != contextDocument()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return nullptr;
    }

    if (ScrollingCoordinator* scrollingCoordinator = document->page()->scrollingCoordinator())
        scrollingCoordinator->updateAfterCompositingChangeIfNeeded();

    LayoutViewItem view = document->layoutViewItem();
    if (!view.isNull()) {
        if (PaintLayerCompositor* compositor = view.compositor()) {
            if (GraphicsLayer* rootLayer = compositor->rootGraphicsLayer()) {
                LayerRectList* rects = LayerRectList::create();
                accumulateLayerRectList(compositor, rootLayer, rects);
                return rects;
            }
        }
    }

    return nullptr;
}

bool Internals::executeCommand(Document* document, const String& name, const String& value, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return false;
    }

    LocalFrame* frame = document->frame();
    return frame->editor().executeCommand(name, value);
}

AtomicString Internals::htmlNamespace()
{
    return HTMLNames::xhtmlNamespaceURI;
}

Vector<AtomicString> Internals::htmlTags()
{
    Vector<AtomicString> tags(HTMLNames::HTMLTagsCount);
    OwnPtr<const HTMLQualifiedName*[]> qualifiedNames = HTMLNames::getHTMLTags();
    for (size_t i = 0; i < HTMLNames::HTMLTagsCount; ++i)
        tags[i] = qualifiedNames[i]->localName();
    return tags;
}

AtomicString Internals::svgNamespace()
{
    return SVGNames::svgNamespaceURI;
}

Vector<AtomicString> Internals::svgTags()
{
    Vector<AtomicString> tags(SVGNames::SVGTagsCount);
    OwnPtr<const SVGQualifiedName*[]> qualifiedNames = SVGNames::getSVGTags();
    for (size_t i = 0; i < SVGNames::SVGTagsCount; ++i)
        tags[i] = qualifiedNames[i]->localName();
    return tags;
}

StaticNodeList* Internals::nodesFromRect(Document* document, int centerX, int centerY, unsigned topPadding, unsigned rightPadding,
    unsigned bottomPadding, unsigned leftPadding, bool ignoreClipping, bool allowChildFrameContent, ExceptionState& exceptionState) const
{
    ASSERT(document);
    if (!document->frame() || !document->frame()->view()) {
        exceptionState.throwDOMException(InvalidAccessError, "No view can be obtained from the provided document.");
        return nullptr;
    }

    LocalFrame* frame = document->frame();
    FrameView* frameView = document->view();
    LayoutViewItem layoutViewItem = document->layoutViewItem();

    if (layoutViewItem.isNull())
        return nullptr;

    float zoomFactor = frame->pageZoomFactor();
    LayoutPoint point = roundedLayoutPoint(FloatPoint(centerX * zoomFactor + frameView->scrollX(), centerY * zoomFactor + frameView->scrollY()));

    HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased;
    if (ignoreClipping)
        hitType |= HitTestRequest::IgnoreClipping;
    if (allowChildFrameContent)
        hitType |= HitTestRequest::AllowChildFrameContent;

    HitTestRequest request(hitType);

    // When ignoreClipping is false, this method returns null for coordinates outside of the viewport.
    if (!request.ignoreClipping() && !frameView->visibleContentRect().intersects(HitTestLocation::rectForPoint(point, topPadding, rightPadding, bottomPadding, leftPadding)))
        return nullptr;

    HeapVector<Member<Node>> matches;
    HitTestResult result(request, point, topPadding, rightPadding, bottomPadding, leftPadding);
    layoutViewItem.hitTest(result);
    copyToVector(result.listBasedTestResult(), matches);

    return StaticNodeList::adopt(matches);
}

bool Internals::hasSpellingMarker(Document* document, int from, int length)
{
    ASSERT(document);
    if (!document->frame())
        return false;

    return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Spelling, from, length);
}

void Internals::setContinuousSpellCheckingEnabled(bool enabled)
{
    if (!contextDocument() || !contextDocument()->frame())
        return;

    if (enabled != contextDocument()->frame()->spellChecker().isContinuousSpellCheckingEnabled())
        contextDocument()->frame()->spellChecker().toggleContinuousSpellChecking();
}

void Internals::setMockHyphenation(const AtomicString& locale)
{
    Hyphenation::setForTesting(locale, adoptRef(new MockHyphenation));
}

bool Internals::isOverwriteModeEnabled(Document* document)
{
    ASSERT(document);
    if (!document->frame())
        return false;

    return document->frame()->editor().isOverwriteModeEnabled();
}

void Internals::toggleOverwriteModeEnabled(Document* document)
{
    ASSERT(document);
    if (!document->frame())
        return;

    document->frame()->editor().toggleOverwriteModeEnabled();
}

unsigned Internals::numberOfLiveNodes() const
{
    return InstanceCounters::counterValue(InstanceCounters::NodeCounter);
}

unsigned Internals::numberOfLiveDocuments() const
{
    return InstanceCounters::counterValue(InstanceCounters::DocumentCounter);
}

String Internals::dumpRefCountedInstanceCounts() const
{
    return WTF::dumpRefCountedInstanceCounts();
}

Vector<String> Internals::consoleMessageArgumentCounts(Document* document) const
{
    FrameHost* host = document->frameHost();
    if (!host)
        return Vector<String>();

    Vector<unsigned> counts = host->consoleMessageStorage().argumentCounts();
    Vector<String> result(counts.size());
    for (size_t i = 0; i < counts.size(); i++)
        result[i] = String::number(counts[i]);
    return result;
}

Vector<unsigned long> Internals::setMemoryCacheCapacities(unsigned long minDeadBytes, unsigned long maxDeadBytes, unsigned long totalBytes)
{
    Vector<unsigned long> result;
    result.append(memoryCache()->minDeadCapacity());
    result.append(memoryCache()->maxDeadCapacity());
    result.append(memoryCache()->capacity());
    memoryCache()->setCapacities(minDeadBytes, maxDeadBytes, totalBytes);
    return result;
}

bool Internals::hasGrammarMarker(Document* document, int from, int length)
{
    ASSERT(document);
    if (!document->frame())
        return false;

    return document->frame()->spellChecker().selectionStartHasMarkerFor(DocumentMarker::Grammar, from, length);
}

unsigned Internals::numberOfScrollableAreas(Document* document)
{
    ASSERT(document);
    if (!document->frame())
        return 0;

    unsigned count = 0;
    LocalFrame* frame = document->frame();
    if (frame->view()->scrollableAreas())
        count += frame->view()->scrollableAreas()->size();

    for (Frame* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
        if (child->isLocalFrame() && toLocalFrame(child)->view() && toLocalFrame(child)->view()->scrollableAreas())
            count += toLocalFrame(child)->view()->scrollableAreas()->size();
    }

    return count;
}

bool Internals::isPageBoxVisible(Document* document, int pageNumber)
{
    ASSERT(document);
    return document->isPageBoxVisible(pageNumber);
}

String Internals::layerTreeAsText(Document* document, ExceptionState& exceptionState) const
{
    return layerTreeAsText(document, 0, exceptionState);
}

String Internals::elementLayerTreeAsText(Element* element, ExceptionState& exceptionState) const
{
    ASSERT(element);
    FrameView* frameView = element->document().view();
    frameView->updateAllLifecyclePhases();

    return elementLayerTreeAsText(element, 0, exceptionState);
}

bool Internals::scrollsWithRespectTo(Element* element1, Element* element2, ExceptionState& exceptionState)
{
    ASSERT(element1 && element2);
    element1->document().view()->updateAllLifecyclePhases();

    LayoutObject* layoutObject1 = element1->layoutObject();
    LayoutObject* layoutObject2 = element2->layoutObject();
    if (!layoutObject1 || !layoutObject1->isBox()) {
        exceptionState.throwDOMException(InvalidAccessError, layoutObject1 ? "The first provided element's layoutObject is not a box." : "The first provided element has no layoutObject.");
        return false;
    }
    if (!layoutObject2 || !layoutObject2->isBox()) {
        exceptionState.throwDOMException(InvalidAccessError, layoutObject2 ? "The second provided element's layoutObject is not a box." : "The second provided element has no layoutObject.");
        return false;
    }

    PaintLayer* layer1 = toLayoutBox(layoutObject1)->layer();
    PaintLayer* layer2 = toLayoutBox(layoutObject2)->layer();
    if (!layer1 || !layer2) {
        exceptionState.throwDOMException(InvalidAccessError, String::format("No PaintLayer can be obtained from the %s provided element.", layer1 ? "second" : "first"));
        return false;
    }

    return layer1->scrollsWithRespectTo(layer2);
}

String Internals::layerTreeAsText(Document* document, unsigned flags, ExceptionState& exceptionState) const
{
    ASSERT(document);
    if (!document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return String();
    }

    document->view()->updateAllLifecyclePhases();

    return document->frame()->layerTreeAsText(flags);
}

String Internals::elementLayerTreeAsText(Element* element, unsigned flags, ExceptionState& exceptionState) const
{
    ASSERT(element);
    element->document().updateStyleAndLayout();

    LayoutObject* layoutObject = element->layoutObject();
    if (!layoutObject || !layoutObject->isBox()) {
        exceptionState.throwDOMException(InvalidAccessError, layoutObject ? "The provided element's layoutObject is not a box." : "The provided element has no layoutObject.");
        return String();
    }

    PaintLayer* layer = toLayoutBox(layoutObject)->layer();
    if (!layer
        || !layer->hasCompositedLayerMapping()
        || !layer->compositedLayerMapping()->mainGraphicsLayer()) {
        // Don't raise exception in these cases which may be normally used in tests.
        return String();
    }

    return layer->compositedLayerMapping()->mainGraphicsLayer()->layerTreeAsText(flags);
}

String Internals::scrollingStateTreeAsText(Document*) const
{
    return String();
}

String Internals::mainThreadScrollingReasons(Document* document, ExceptionState& exceptionState) const
{
    ASSERT(document);
    if (!document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return String();
    }

    document->frame()->view()->updateAllLifecyclePhases();

    Page* page = document->page();
    if (!page)
        return String();

    return page->mainThreadScrollingReasonsAsText();
}

ClientRectList* Internals::nonFastScrollableRects(Document* document, ExceptionState& exceptionState) const
{
    ASSERT(document);
    if (!document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return nullptr;
    }

    Page* page = document->page();
    if (!page)
        return nullptr;

    return page->nonFastScrollableRects(document->frame());
}

void Internals::evictAllResources() const
{
    memoryCache()->evictResources();
}

String Internals::counterValue(Element* element)
{
    if (!element)
        return String();

    return counterValueForElement(element);
}

int Internals::pageNumber(Element* element, float pageWidth, float pageHeight, ExceptionState& exceptionState)
{
    if (!element)
        return 0;

    if (pageWidth <= 0 || pageHeight <= 0) {
        exceptionState.throwDOMException(V8TypeError, "Page width and height must be larger than 0.");
        return 0;
    }

    return PrintContext::pageNumberForElement(element, FloatSize(pageWidth, pageHeight));
}

Vector<String> Internals::iconURLs(Document* document, int iconTypesMask) const
{
    Vector<IconURL> iconURLs = document->iconURLs(iconTypesMask);
    Vector<String> array;

    for (auto& iconURL : iconURLs)
        array.append(iconURL.m_iconURL.getString());

    return array;
}

Vector<String> Internals::shortcutIconURLs(Document* document) const
{
    return iconURLs(document, Favicon);
}

Vector<String> Internals::allIconURLs(Document* document) const
{
    return iconURLs(document, Favicon | TouchIcon | TouchPrecomposedIcon);
}

int Internals::numberOfPages(float pageWidth, float pageHeight, ExceptionState& exceptionState)
{
    if (!frame())
        return -1;

    if (pageWidth <= 0 || pageHeight <= 0) {
        exceptionState.throwDOMException(V8TypeError, "Page width and height must be larger than 0.");
        return -1;
    }

    return PrintContext::numberOfPages(frame(), FloatSize(pageWidth, pageHeight));
}

String Internals::pageProperty(String propertyName, int pageNumber, ExceptionState& exceptionState) const
{
    if (!frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "No frame is available.");
        return String();
    }

    return PrintContext::pageProperty(frame(), propertyName.utf8().data(), pageNumber);
}

String Internals::pageSizeAndMarginsInPixels(int pageNumber, int width, int height, int marginTop, int marginRight, int marginBottom, int marginLeft, ExceptionState& exceptionState) const
{
    if (!frame()) {
        exceptionState.throwDOMException(InvalidAccessError, "No frame is available.");
        return String();
    }

    return PrintContext::pageSizeAndMarginsInPixels(frame(), pageNumber, width, height, marginTop, marginRight, marginBottom, marginLeft);
}

void Internals::setPageScaleFactor(float scaleFactor, ExceptionState& exceptionState)
{
    Document* document = contextDocument();
    if (!document || !document->page()) {
        exceptionState.throwDOMException(InvalidAccessError, document ? "The document's page cannot be retrieved." : "No context document can be obtained.");
        return;
    }
    Page* page = document->page();
    page->frameHost().visualViewport().setScale(scaleFactor);
}

void Internals::setPageScaleFactorLimits(float minScaleFactor, float maxScaleFactor, ExceptionState& exceptionState)
{
    Document* document = contextDocument();
    if (!document || !document->page()) {
        exceptionState.throwDOMException(InvalidAccessError, document ? "The document's page cannot be retrieved." : "No context document can be obtained.");
        return;
    }

    Page* page = document->page();
    page->frameHost().setDefaultPageScaleLimits(minScaleFactor, maxScaleFactor);
}

bool Internals::magnifyScaleAroundAnchor(float scaleFactor, float x, float y)
{
    return frame()->host()->visualViewport().magnifyScaleAroundAnchor(scaleFactor, FloatPoint(x, y));
}

void Internals::setIsCursorVisible(Document* document, bool isVisible, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->page()) {
        exceptionState.throwDOMException(InvalidAccessError, "No context document can be obtained.");
        return;
    }
    document->page()->setIsCursorVisible(isVisible);
}

double Internals::effectiveMediaVolume(HTMLMediaElement* mediaElement)
{
    ASSERT(mediaElement);
    return mediaElement->effectiveMediaVolume();
}

String Internals::effectivePreload(HTMLMediaElement* mediaElement)
{
    ASSERT(mediaElement);
    return mediaElement->effectivePreload();
}

void Internals::mediaPlayerRemoteRouteAvailabilityChanged(HTMLMediaElement* mediaElement, bool available)
{
    ASSERT(mediaElement);
    mediaElement->remoteRouteAvailabilityChanged(available);
}

void Internals::mediaPlayerPlayingRemotelyChanged(HTMLMediaElement* mediaElement, bool remote)
{
    ASSERT(mediaElement);
    if (remote)
        mediaElement->connectedToRemoteDevice();
    else
        mediaElement->disconnectedFromRemoteDevice();
}

void Internals::setAllowHiddenVolumeControls(HTMLMediaElement* mediaElement, bool allow)
{
    ASSERT(mediaElement);
    mediaElement->setAllowHiddenVolumeControls(allow);
}

void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme)
{
    SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(scheme);
}

void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(const String& scheme, const Vector<String>& policyAreas)
{
    uint32_t policyAreasEnum = SchemeRegistry::PolicyAreaNone;
    for (const auto& policyArea : policyAreas) {
        if (policyArea == "img")
            policyAreasEnum |= SchemeRegistry::PolicyAreaImage;
        else if (policyArea == "style")
            policyAreasEnum |= SchemeRegistry::PolicyAreaStyle;
    }
    SchemeRegistry::registerURLSchemeAsBypassingContentSecurityPolicy(
        scheme, static_cast<SchemeRegistry::PolicyAreas>(policyAreasEnum));
}

void Internals::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(const String& scheme)
{
    SchemeRegistry::removeURLSchemeRegisteredAsBypassingContentSecurityPolicy(scheme);
}

TypeConversions* Internals::typeConversions() const
{
    return TypeConversions::create();
}

PrivateScriptTest* Internals::privateScriptTest() const
{
    return PrivateScriptTest::create(frame()->document());
}

DictionaryTest* Internals::dictionaryTest() const
{
    return DictionaryTest::create();
}

UnionTypesTest* Internals::unionTypesTest() const
{
    return UnionTypesTest::create();
}

Vector<String> Internals::getReferencedFilePaths() const
{
    return frame()->loader().currentItem()->getReferencedFilePaths();
}

void Internals::startTrackingRepaints(Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->view()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return;
    }

    FrameView* frameView = document->view();
    frameView->updateAllLifecyclePhases();
    frameView->setTracksPaintInvalidations(true);
}

void Internals::stopTrackingRepaints(Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->view()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return;
    }

    FrameView* frameView = document->view();
    frameView->updateAllLifecyclePhases();
    frameView->setTracksPaintInvalidations(false);
}

void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(Node* node, ExceptionState& exceptionState)
{
    Document* document;
    if (!node) {
        document = contextDocument();
    } else if (node->isDocumentNode()) {
        document = toDocument(node);
    } else if (isHTMLIFrameElement(*node)) {
        document = toHTMLIFrameElement(*node).contentDocument();
    } else {
        exceptionState.throwTypeError("The node provided is neither a document nor an IFrame.");
        return;
    }
    document->updateStyleAndLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasksSynchronously);
}

void Internals::forceFullRepaint(Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->view()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return;
    }

    LayoutViewItem layoutViewItem = document->layoutViewItem();
    if (!layoutViewItem.isNull())
        layoutViewItem.invalidatePaintForViewAndCompositedLayers();
}

ClientRectList* Internals::draggableRegions(Document* document, ExceptionState& exceptionState)
{
    return annotatedRegions(document, true, exceptionState);
}

ClientRectList* Internals::nonDraggableRegions(Document* document, ExceptionState& exceptionState)
{
    return annotatedRegions(document, false, exceptionState);
}

ClientRectList* Internals::annotatedRegions(Document* document, bool draggable, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (!document->view()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return ClientRectList::create();
    }

    document->updateStyleAndLayout();
    document->view()->updateDocumentAnnotatedRegions();
    Vector<AnnotatedRegionValue> regions = document->annotatedRegions();

    Vector<FloatQuad> quads;
    for (size_t i = 0; i < regions.size(); ++i) {
        if (regions[i].draggable == draggable)
            quads.append(FloatQuad(FloatRect(regions[i].bounds)));
    }
    return ClientRectList::create(quads);
}

static const char* cursorTypeToString(Cursor::Type cursorType)
{
    switch (cursorType) {
    case Cursor::Pointer: return "Pointer";
    case Cursor::Cross: return "Cross";
    case Cursor::Hand: return "Hand";
    case Cursor::IBeam: return "IBeam";
    case Cursor::Wait: return "Wait";
    case Cursor::Help: return "Help";
    case Cursor::EastResize: return "EastResize";
    case Cursor::NorthResize: return "NorthResize";
    case Cursor::NorthEastResize: return "NorthEastResize";
    case Cursor::NorthWestResize: return "NorthWestResize";
    case Cursor::SouthResize: return "SouthResize";
    case Cursor::SouthEastResize: return "SouthEastResize";
    case Cursor::SouthWestResize: return "SouthWestResize";
    case Cursor::WestResize: return "WestResize";
    case Cursor::NorthSouthResize: return "NorthSouthResize";
    case Cursor::EastWestResize: return "EastWestResize";
    case Cursor::NorthEastSouthWestResize: return "NorthEastSouthWestResize";
    case Cursor::NorthWestSouthEastResize: return "NorthWestSouthEastResize";
    case Cursor::ColumnResize: return "ColumnResize";
    case Cursor::RowResize: return "RowResize";
    case Cursor::MiddlePanning: return "MiddlePanning";
    case Cursor::EastPanning: return "EastPanning";
    case Cursor::NorthPanning: return "NorthPanning";
    case Cursor::NorthEastPanning: return "NorthEastPanning";
    case Cursor::NorthWestPanning: return "NorthWestPanning";
    case Cursor::SouthPanning: return "SouthPanning";
    case Cursor::SouthEastPanning: return "SouthEastPanning";
    case Cursor::SouthWestPanning: return "SouthWestPanning";
    case Cursor::WestPanning: return "WestPanning";
    case Cursor::Move: return "Move";
    case Cursor::VerticalText: return "VerticalText";
    case Cursor::Cell: return "Cell";
    case Cursor::ContextMenu: return "ContextMenu";
    case Cursor::Alias: return "Alias";
    case Cursor::Progress: return "Progress";
    case Cursor::NoDrop: return "NoDrop";
    case Cursor::Copy: return "Copy";
    case Cursor::None: return "None";
    case Cursor::NotAllowed: return "NotAllowed";
    case Cursor::ZoomIn: return "ZoomIn";
    case Cursor::ZoomOut: return "ZoomOut";
    case Cursor::Grab: return "Grab";
    case Cursor::Grabbing: return "Grabbing";
    case Cursor::Custom: return "Custom";
    }

    ASSERT_NOT_REACHED();
    return "UNKNOWN";
}

String Internals::getCurrentCursorInfo()
{
    Cursor cursor = frame()->page()->chromeClient().lastSetCursorForTesting();

    StringBuilder result;
    result.appendLiteral("type=");
    result.append(cursorTypeToString(cursor.getType()));
    result.appendLiteral(" hotSpot=");
    result.appendNumber(cursor.hotSpot().x());
    result.append(',');
    result.appendNumber(cursor.hotSpot().y());
    if (cursor.getImage()) {
        IntSize size = cursor.getImage()->size();
        result.appendLiteral(" image=");
        result.appendNumber(size.width());
        result.append('x');
        result.appendNumber(size.height());
    }
    if (cursor.imageScaleFactor() != 1) {
        result.appendLiteral(" scale=");
        NumberToStringBuffer buffer;
        result.append(numberToFixedPrecisionString(cursor.imageScaleFactor(), 8, buffer, true));
    }

    return result.toString();
}

bool Internals::cursorUpdatePending() const
{
    return frame()->eventHandler().cursorUpdatePending();
}

DOMArrayBuffer* Internals::serializeObject(PassRefPtr<SerializedScriptValue> value) const
{
    String stringValue = value->toWireString();
    DOMArrayBuffer* buffer = DOMArrayBuffer::createUninitialized(stringValue.length(), sizeof(UChar));
    stringValue.copyTo(static_cast<UChar*>(buffer->data()), 0, stringValue.length());
    return buffer;
}

PassRefPtr<SerializedScriptValue> Internals::deserializeBuffer(DOMArrayBuffer* buffer) const
{
    String value(static_cast<const UChar*>(buffer->data()), buffer->byteLength() / sizeof(UChar));
    return SerializedScriptValue::create(value);
}

void Internals::forceReload(bool bypassCache)
{
    frame()->reload(bypassCache ? FrameLoadTypeReloadBypassingCache : FrameLoadTypeReload, ClientRedirectPolicy::NotClientRedirect);
}

ClientRect* Internals::selectionBounds(ExceptionState& exceptionState)
{
    Document* document = contextDocument();
    if (!document || !document->frame()) {
        exceptionState.throwDOMException(InvalidAccessError, document ? "The document's frame cannot be retrieved." : "No context document can be obtained.");
        return nullptr;
    }

    return ClientRect::create(FloatRect(document->frame()->selection().bounds()));
}

String Internals::markerTextForListItem(Element* element)
{
    ASSERT(element);
    return blink::markerTextForListItem(element);
}

String Internals::getImageSourceURL(Element* element)
{
    ASSERT(element);
    return element->imageSourceURL();
}

String Internals::selectMenuListText(HTMLSelectElement* select)
{
    ASSERT(select);
    LayoutObject* layoutObject = select->layoutObject();
    if (!layoutObject || !layoutObject->isMenuList())
        return String();

    LayoutMenuListItem menuListItem = LayoutMenuListItem(toLayoutMenuList(layoutObject));
    return menuListItem.text();
}

bool Internals::isSelectPopupVisible(Node* node)
{
    ASSERT(node);
    if (!isHTMLSelectElement(*node))
        return false;
    return toHTMLSelectElement(*node).popupIsVisible();
}

bool Internals::selectPopupItemStyleIsRtl(Node* node, int itemIndex)
{
    if (!node || !isHTMLSelectElement(*node))
        return false;

    HTMLSelectElement& select = toHTMLSelectElement(*node);
    if (itemIndex < 0 || static_cast<size_t>(itemIndex) >= select.listItems().size())
        return false;
    const ComputedStyle* itemStyle = select.itemComputedStyle(*select.listItems()[itemIndex]);
    return itemStyle && itemStyle->direction() == RTL;
}

int Internals::selectPopupItemStyleFontHeight(Node* node, int itemIndex)
{
    if (!node || !isHTMLSelectElement(*node))
        return false;

    HTMLSelectElement& select = toHTMLSelectElement(*node);
    if (itemIndex < 0 || static_cast<size_t>(itemIndex) >= select.listItems().size())
        return false;
    const ComputedStyle* itemStyle = select.itemComputedStyle(*select.listItems()[itemIndex]);
    return itemStyle ? itemStyle->font().getFontMetrics().height() : 0;
}

void Internals::resetTypeAheadSession(HTMLSelectElement* select)
{
    ASSERT(select);
    select->resetTypeAheadSessionForTesting();
}

bool Internals::loseSharedGraphicsContext3D()
{
    OwnPtr<WebGraphicsContext3DProvider> sharedProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
    if (!sharedProvider)
        return false;
    gpu::gles2::GLES2Interface* sharedGL = sharedProvider->contextGL();
    sharedGL->LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_EXT, GL_INNOCENT_CONTEXT_RESET_EXT);
    // To prevent tests that call loseSharedGraphicsContext3D from being
    // flaky, we call finish so that the context is guaranteed to be lost
    // synchronously (i.e. before returning).
    sharedGL->Finish();
    return true;
}

void Internals::forceCompositingUpdate(Document* document, ExceptionState& exceptionState)
{
    ASSERT(document);
    if (document->layoutViewItem().isNull()) {
        exceptionState.throwDOMException(InvalidAccessError, "The document provided is invalid.");
        return;
    }

    document->frame()->view()->updateAllLifecyclePhases();
}

void Internals::setZoomFactor(float factor)
{
    frame()->setPageZoomFactor(factor);
}

void Internals::setShouldRevealPassword(Element* element, bool reveal, ExceptionState& exceptionState)
{
    ASSERT(element);
    if (!isHTMLInputElement(element)) {
        exceptionState.throwDOMException(InvalidNodeTypeError, "The element provided is not an INPUT.");
        return;
    }

    return toHTMLInputElement(*element).setShouldRevealPassword(reveal);
}

namespace {

class AddOneFunction : public ScriptFunction {
public:
    static v8::Local<v8::Function> createFunction(ScriptState* scriptState)
    {
        AddOneFunction* self = new AddOneFunction(scriptState);
        return self->bindToV8Function();
    }

private:
    explicit AddOneFunction(ScriptState* scriptState)
        : ScriptFunction(scriptState)
    {
    }

    ScriptValue call(ScriptValue value) override
    {
        v8::Local<v8::Value> v8Value = value.v8Value();
        ASSERT(v8Value->IsNumber());
        int intValue = v8Value.As<v8::Integer>()->Value();
        return ScriptValue(getScriptState(), v8::Integer::New(getScriptState()->isolate(), intValue + 1));
    }
};

} // namespace

ScriptPromise Internals::createResolvedPromise(ScriptState* scriptState, ScriptValue value)
{
    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
    ScriptPromise promise = resolver->promise();
    resolver->resolve(value);
    return promise;
}

ScriptPromise Internals::createRejectedPromise(ScriptState* scriptState, ScriptValue value)
{
    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
    ScriptPromise promise = resolver->promise();
    resolver->reject(value);
    return promise;
}

ScriptPromise Internals::addOneToPromise(ScriptState* scriptState, ScriptPromise promise)
{
    return promise.then(AddOneFunction::createFunction(scriptState));
}

ScriptPromise Internals::promiseCheck(ScriptState* scriptState, long arg1, bool arg2, const Dictionary& arg3, const String& arg4, const Vector<String>& arg5, ExceptionState& exceptionState)
{
    if (arg2)
        return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
    exceptionState.throwDOMException(InvalidStateError, "Thrown from the native implementation.");
    return ScriptPromise();
}

ScriptPromise Internals::promiseCheckWithoutExceptionState(ScriptState* scriptState, const Dictionary& arg1, const String& arg2, const Vector<String>& arg3)
{
    return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
}

ScriptPromise Internals::promiseCheckRange(ScriptState* scriptState, long arg1)
{
    return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
}

ScriptPromise Internals::promiseCheckOverload(ScriptState* scriptState, Location*)
{
    return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
}

ScriptPromise Internals::promiseCheckOverload(ScriptState* scriptState, Document*)
{
    return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
}

ScriptPromise Internals::promiseCheckOverload(ScriptState* scriptState, Location*, long, long)
{
    return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(), "done"));
}

DEFINE_TRACE(Internals)
{
    visitor->trace(m_runtimeFlags);
    ContextLifecycleObserver::trace(visitor);
}

void Internals::setValueForUser(Element* element, const String& value)
{
    toHTMLInputElement(element)->setValueForUser(value);
}

String Internals::textSurroundingNode(Node* node, int x, int y, unsigned long maxLength)
{
    if (!node || !node->layoutObject())
        return String();
    blink::WebPoint point(x, y);
    SurroundingText surroundingText(createVisiblePosition(node->layoutObject()->positionForPoint(static_cast<IntPoint>(point))).deepEquivalent().parentAnchoredEquivalent(), maxLength);
    return surroundingText.content();
}

void Internals::setFocused(bool focused)
{
    frame()->page()->focusController().setFocused(focused);
}

void Internals::setInitialFocus(bool reverse)
{
    frame()->document()->clearFocusedElement();
    frame()->page()->focusController().setInitialFocus(reverse ? WebFocusTypeBackward : WebFocusTypeForward);
}

bool Internals::ignoreLayoutWithPendingStylesheets(Document* document)
{
    ASSERT(document);
    return document->ignoreLayoutWithPendingStylesheets();
}

void Internals::setNetworkStateNotifierTestOnly(bool testOnly)
{
    networkStateNotifier().setTestUpdatesOnly(testOnly);
}

void Internals::setNetworkConnectionInfo(const String& type, double downlinkMaxMbps, ExceptionState& exceptionState)
{
    WebConnectionType webtype;
    if (type == "cellular2g") {
        webtype = WebConnectionTypeCellular2G;
    } else if (type == "cellular3g") {
        webtype = WebConnectionTypeCellular3G;
    } else if (type == "cellular4g") {
        webtype = WebConnectionTypeCellular4G;
    } else if (type == "bluetooth") {
        webtype = WebConnectionTypeBluetooth;
    } else if (type == "ethernet") {
        webtype = WebConnectionTypeEthernet;
    } else if (type == "wifi") {
        webtype = WebConnectionTypeWifi;
    } else if (type == "wimax") {
        webtype = WebConnectionTypeWimax;
    } else if (type == "other") {
        webtype = WebConnectionTypeOther;
    } else if (type == "none") {
        webtype = WebConnectionTypeNone;
    } else if (type == "unknown") {
        webtype = WebConnectionTypeUnknown;
    } else {
        exceptionState.throwDOMException(NotFoundError, ExceptionMessages::failedToEnumerate("connection type", type));
        return;
    }
    networkStateNotifier().setWebConnectionForTest(webtype, downlinkMaxMbps);
}

unsigned Internals::countHitRegions(CanvasRenderingContext* context)
{
    return context->hitRegionsCount();
}

bool Internals::isInCanvasFontCache(Document* document, const String& fontString)
{
    return document->canvasFontCache()->isInCache(fontString);
}

unsigned Internals::canvasFontCacheMaxFonts()
{
    return CanvasFontCache::maxFonts();
}

void Internals::setScrollChain(
    ScrollState* scrollState, const HeapVector<Member<Element>>& elements, ExceptionState&)
{
    std::deque<int> scrollChain;
    for (size_t i = 0; i < elements.size(); ++i)
        scrollChain.push_back(DOMNodeIds::idForNode(elements[i].get()));
    scrollState->setScrollChain(scrollChain);
}

void Internals::forceBlinkGCWithoutV8GC()
{
    ThreadState::current()->setGCState(ThreadState::FullGCScheduled);
}

String Internals::selectedHTMLForClipboard()
{
    return frame()->selection().selectedHTMLForClipboard();
}

String Internals::selectedTextForClipboard()
{
    return frame()->selection().selectedTextForClipboard();
}

void Internals::setVisualViewportOffset(int x, int y)
{
    frame()->host()->visualViewport().setLocation(FloatPoint(x, y));
}

int Internals::visualViewportHeight()
{
    return expandedIntSize(frame()->host()->visualViewport().visibleRect().size()).height();
}

int Internals::visualViewportWidth()
{
    return expandedIntSize(frame()->host()->visualViewport().visibleRect().size()).width();
}

double Internals::visualViewportScrollX()
{
    return frame()->view()->getScrollableArea()->scrollPositionDouble().x();
}

double Internals::visualViewportScrollY()
{
    return frame()->view()->getScrollableArea()->scrollPositionDouble().y();
}

ValueIterable<int>::IterationSource* Internals::startIteration(ScriptState*, ExceptionState&)
{
    return new InternalsIterationSource();
}

bool Internals::isUseCounted(Document* document, int useCounterId)
{
    if (useCounterId < 0 || useCounterId >= UseCounter::NumberOfFeatures)
        return false;
    return UseCounter::isCounted(*document, static_cast<UseCounter::Feature>(useCounterId));
}

bool Internals::isCSSPropertyUseCounted(Document* document, const String& propertyName)
{
    return UseCounter::isCounted(*document, propertyName);
}

String Internals::unscopeableAttribute()
{
    return "unscopeableAttribute";
}

String Internals::unscopeableMethod()
{
    return "unscopeableMethod";
}

ClientRectList* Internals::focusRingRects(Element* element)
{
    Vector<LayoutRect> rects;
    if (element && element->layoutObject())
        element->layoutObject()->addOutlineRects(rects, LayoutPoint(), LayoutObject::IncludeBlockVisualOverflow);
    return ClientRectList::create(rects);
}

ClientRectList* Internals::outlineRects(Element* element)
{
    Vector<LayoutRect> rects;
    if (element && element->layoutObject())
        element->layoutObject()->addOutlineRects(rects, LayoutPoint(), LayoutObject::DontIncludeBlockVisualOverflow);
    return ClientRectList::create(rects);
}

void Internals::setCapsLockState(bool enabled)
{
    PlatformKeyboardEvent::setCurrentCapsLockState(enabled ?
        PlatformKeyboardEvent::OverrideCapsLockState::On : PlatformKeyboardEvent::OverrideCapsLockState::Off);
}

bool Internals::setScrollbarVisibilityInScrollableArea(Node* node, bool visible)
{
    if (ScrollableArea* scrollableArea = scrollableAreaForNode(node))
        return scrollableArea->scrollAnimator().setScrollbarsVisibleForTesting(visible);
    return false;
}

double Internals::monotonicTimeToZeroBasedDocumentTime(double platformTime, ExceptionState& exceptionState)
{
    Document* document = contextDocument();
    if (!document) {
        exceptionState.throwDOMException(InvalidAccessError, "No context document is available.");
        return 0;
    }

    return document->loader()->timing().monotonicTimeToZeroBasedDocumentTime(platformTime);
}

void Internals::setMediaElementNetworkState(HTMLMediaElement* mediaElement, int state)
{
    ASSERT(mediaElement);
    ASSERT(state >= WebMediaPlayer::NetworkState::NetworkStateEmpty);
    ASSERT(state <= WebMediaPlayer::NetworkState::NetworkStateDecodeError);
    mediaElement->setNetworkState(static_cast<WebMediaPlayer::NetworkState>(state));
}

// TODO(liberato): remove once autoplay gesture override experiment concludes.
void Internals::triggerAutoplayViewportCheck(HTMLMediaElement* element)
{
    element->triggerAutoplayViewportCheckForTesting();
}

String Internals::getScrollAnimationState(Node* node) const
{
    if (ScrollableArea* scrollableArea = scrollableAreaForNode(node))
        return scrollableArea->scrollAnimator().runStateAsText();
    return String();
}

String Internals::getProgrammaticScrollAnimationState(Node* node) const
{
    if (ScrollableArea* scrollableArea = scrollableAreaForNode(node))
        return scrollableArea->programmaticScrollAnimator().runStateAsText();
    return String();
}

} // namespace blink
