/*
 * 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 <deque>
#include <memory>

#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/V8IteratorResultValue.h"
#include "core/HTMLNames.h"
#include "core/SVGNames.h"
#include "core/animation/DocumentTimeline.h"
#include "core/dom/ClientRect.h"
#include "core/dom/ClientRectList.h"
#include "core/dom/DOMArrayBuffer.h"
#include "core/dom/DOMNodeIds.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/ElementShadowV0.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/IdleSpellCheckCallback.h"
#include "core/editing/spellcheck/SpellCheckRequester.h"
#include "core/editing/spellcheck/SpellChecker.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/geometry/DOMPoint.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/HTMLVideoElement.h"
#include "core/html/canvas/CanvasFontCache.h"
#include "core/html/canvas/CanvasRenderingContext.h"
#include "core/html/forms/FormController.h"
#include "core/html/forms/TextControlInnerElements.h"
#include "core/html/shadow/ShadowElementNames.h"
#include "core/input/EventHandler.h"
#include "core/input/KeyboardEventManager.h"
#include "core/inspector/MainThreadDebugger.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/Page.h"
#include "core/page/PrintContext.h"
#include "core/page/scrolling/ScrollState.h"
#include "core/paint/PaintLayer.h"
#include "core/probe/CoreProbes.h"
#include "core/svg/SVGImageElement.h"
#include "core/testing/CallbackFunctionTest.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/OriginTrialsTest.h"
#include "core/testing/RecordTest.h"
#include "core/testing/SequenceTest.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/InstanceCounters.h"
#include "platform/Language.h"
#include "platform/LayoutLocale.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/bindings/V8ThrowException.h"
#include "platform/geometry/IntRect.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/heap/Handle.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/loader/fetch/MemoryCache.h"
#include "platform/loader/fetch/ResourceFetcher.h"
#include "platform/loader/fetch/ResourceLoadPriority.h"
#include "platform/network/NetworkStateNotifier.h"
#include "platform/scroll/ProgrammaticScrollAnimator.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "platform/testing/URLTestHelpers.h"
#include "platform/weborigin/SchemeRegistry.h"
#include "platform/wtf/Optional.h"
#include "platform/wtf/PtrUtil.h"
#include "platform/wtf/dtoa.h"
#include "platform/wtf/text/StringBuffer.h"
#include "public/platform/Platform.h"
#include "public/platform/WebConnectionType.h"
#include "public/platform/WebGraphicsContext3DProvider.h"
#include "public/platform/WebLayer.h"
#include "public/platform/modules/remoteplayback/WebRemotePlaybackAvailability.h"
#include "v8/include/v8.h"

namespace blink {

namespace {

class UseCounterObserverImpl final : public UseCounter::Observer {
  WTF_MAKE_NONCOPYABLE(UseCounterObserverImpl);

 public:
  UseCounterObserverImpl(ScriptPromiseResolver* resolver,
                         UseCounter::Feature feature)
      : resolver_(resolver), feature_(feature) {}

  bool OnCountFeature(UseCounter::Feature feature) final {
    if (feature_ != feature)
      return false;
    resolver_->Resolve(feature);
    return true;
  }

  DEFINE_INLINE_VIRTUAL_TRACE() {
    UseCounter::Observer::Trace(visitor);
    visitor->Trace(resolver_);
  }

 private:
  Member<ScriptPromiseResolver> resolver_;
  UseCounter::Feature feature_;
};

}  // namespace

static WTF::Optional<DocumentMarker::MarkerType> MarkerTypeFrom(
    const String& marker_type) {
  if (DeprecatedEqualIgnoringCase(marker_type, "Spelling"))
    return DocumentMarker::kSpelling;
  if (DeprecatedEqualIgnoringCase(marker_type, "Grammar"))
    return DocumentMarker::kGrammar;
  if (DeprecatedEqualIgnoringCase(marker_type, "TextMatch"))
    return DocumentMarker::kTextMatch;
  return WTF::nullopt;
}

static WTF::Optional<DocumentMarker::MarkerTypes> MarkerTypesFrom(
    const String& marker_type) {
  if (marker_type.IsEmpty() || DeprecatedEqualIgnoringCase(marker_type, "all"))
    return DocumentMarker::AllMarkers();
  WTF::Optional<DocumentMarker::MarkerType> type = MarkerTypeFrom(marker_type);
  if (!type)
    return WTF::nullopt;
  return DocumentMarker::MarkerTypes(type.value());
}

static SpellCheckRequester* GetSpellCheckRequester(Document* document) {
  if (!document || !document->GetFrame())
    return 0;
  return &document->GetFrame()->GetSpellChecker().GetSpellCheckRequester();
}

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

  if (node->IsDocumentNode()) {
    // This can be removed after root layer scrolling is enabled.
    if (FrameView* frame_view = ToDocument(node)->View())
      return frame_view->LayoutViewportScrollableArea();
  }

  LayoutObject* layout_object = node->GetLayoutObject();
  if (!layout_object || !layout_object->IsBox())
    return nullptr;

  return ToLayoutBox(layout_object)->GetScrollableArea();
}

static RuntimeEnabledFeatures::Backup* g_s_features_backup = nullptr;

void Internals::ResetToConsistentState(Page* page) {
  DCHECK(page);

  if (!g_s_features_backup)
    g_s_features_backup = new RuntimeEnabledFeatures::Backup;
  g_s_features_backup->restore();
  page->SetIsCursorVisible(true);
  page->SetPageScaleFactor(1);
  page->DeprecatedLocalMainFrame()
      ->View()
      ->LayoutViewportScrollableArea()
      ->SetScrollOffset(ScrollOffset(), kProgrammaticScroll);
  OverrideUserPreferredLanguages(Vector<AtomicString>());
  if (!page->DeprecatedLocalMainFrame()
           ->GetSpellChecker()
           .IsSpellCheckingEnabled())
    page->DeprecatedLocalMainFrame()
        ->GetSpellChecker()
        .ToggleSpellCheckingEnabled();
  if (page->DeprecatedLocalMainFrame()->GetEditor().IsOverwriteModeEnabled())
    page->DeprecatedLocalMainFrame()->GetEditor().ToggleOverwriteModeEnabled();

  if (ScrollingCoordinator* scrolling_coordinator =
          page->GetScrollingCoordinator())
    scrolling_coordinator->Reset();

  KeyboardEventManager::SetCurrentCapsLockState(
      OverrideCapsLockState::kDefault);
}

Internals::Internals(ExecutionContext* context)
    : runtime_flags_(InternalRuntimeFlags::create()),
      document_(ToDocument(context)) {
  document_->Fetcher()->EnableIsPreloadedForTest();
}

LocalFrame* Internals::GetFrame() const {
  if (!document_)
    return nullptr;
  return document_->GetFrame();
}

InternalSettings* Internals::settings() const {
  if (!document_)
    return 0;
  Page* page = document_->GetPage();
  if (!page)
    return 0;
  return InternalSettings::From(*page);
}

InternalRuntimeFlags* Internals::runtimeFlags() const {
  return runtime_flags_.Get();
}

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

GCObservation* Internals::observeGC(ScriptValue script_value) {
  v8::Local<v8::Value> observed_value = script_value.V8Value();
  DCHECK(!observed_value.IsEmpty());
  if (observed_value->IsNull() || observed_value->IsUndefined()) {
    V8ThrowException::ThrowTypeError(v8::Isolate::GetCurrent(),
                                     "value to observe is null or undefined");
    return nullptr;
  }

  return GCObservation::Create(observed_value);
}

unsigned Internals::updateStyleAndReturnAffectedElementCount(
    ExceptionState& exception_state) const {
  if (!document_) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "No context document is available.");
    return 0;
  }

  unsigned before_count = document_->GetStyleEngine().StyleForElementCount();
  document_->UpdateStyleAndLayoutTree();
  return document_->GetStyleEngine().StyleForElementCount() - before_count;
}

unsigned Internals::needsLayoutCount(ExceptionState& exception_state) const {
  LocalFrame* context_frame = GetFrame();
  if (!context_frame) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "No context frame is available.");
    return 0;
  }

  bool is_partial;
  unsigned needs_layout_objects;
  unsigned total_objects;
  context_frame->View()->CountObjectsNeedingLayout(needs_layout_objects,
                                                   total_objects, is_partial);
  return needs_layout_objects;
}

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

  return doc->GetLayoutViewItem().HitTestCount();
}

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

  return doc->GetLayoutViewItem().HitTestCacheHits();
}

Element* Internals::elementFromPoint(Document* doc,
                                     double x,
                                     double y,
                                     bool ignore_clipping,
                                     bool allow_child_frame_content,
                                     ExceptionState& exception_state) const {
  if (!doc) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "Must supply document to check");
    return 0;
  }

  if (doc->GetLayoutViewItem().IsNull())
    return 0;

  HitTestRequest::HitTestRequestType hit_type =
      HitTestRequest::kReadOnly | HitTestRequest::kActive;
  if (ignore_clipping)
    hit_type |= HitTestRequest::kIgnoreClipping;
  if (allow_child_frame_content)
    hit_type |= HitTestRequest::kAllowChildFrameContent;

  HitTestRequest request(hit_type);

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

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

  if (doc->GetLayoutViewItem().IsNull())
    return;

  doc->GetLayoutViewItem().ClearHitTestCache();
}

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

bool Internals::isPreloadedBy(const String& url, Document* document) {
  if (!document)
    return false;
  return document->Fetcher()->IsPreloadedForTest(document->CompleteURL(url));
}

bool Internals::isLoading(const String& url) {
  if (!document_)
    return false;
  const String cache_identifier = document_->Fetcher()->GetCacheIdentifier();
  Resource* resource = GetMemoryCache()->ResourceForURL(
      document_->CompleteURL(url), cache_identifier);
  // We check loader() here instead of isLoading(), because a multipart
  // ImageResource lies isLoading() == false after the first part is loaded.
  return resource && resource->Loader();
}

bool Internals::isLoadingFromMemoryCache(const String& url) {
  if (!document_)
    return false;
  const String cache_identifier = document_->Fetcher()->GetCacheIdentifier();
  Resource* resource = GetMemoryCache()->ResourceForURL(
      document_->CompleteURL(url), cache_identifier);
  return resource && resource->GetStatus() == ResourceStatus::kCached;
}

int Internals::getResourcePriority(const String& url, Document* document) {
  if (!document)
    return ResourceLoadPriority::kResourceLoadPriorityUnresolved;

  Resource* resource = document->Fetcher()->AllResources().at(
      URLTestHelpers::ToKURL(url.Utf8().data()));

  if (!resource)
    return ResourceLoadPriority::kResourceLoadPriorityUnresolved;

  return resource->GetResourceRequest().Priority();
}

String Internals::getResourceHeader(const String& url,
                                    const String& header,
                                    Document* document) {
  if (!document)
    return String();
  Resource* resource = document->Fetcher()->AllResources().at(
      URLTestHelpers::ToKURL(url.Utf8().data()));
  if (!resource)
    return String();
  return resource->GetResourceRequest().HttpHeaderField(header.Utf8().data());
}

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

bool Internals::isValidContentSelect(Element* insertion_point,
                                     ExceptionState& exception_state) {
  DCHECK(insertion_point);
  if (!insertion_point->IsInsertionPoint()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The element is not an insertion point.");
    return false;
  }

  return isHTMLContentElement(*insertion_point) &&
         toHTMLContentElement(*insertion_point).IsSelectValid();
}

Node* Internals::treeScopeRootNode(Node* node) {
  DCHECK(node);
  return &node->GetTreeScope().RootNode();
}

Node* Internals::parentTreeScope(Node* node) {
  DCHECK(node);
  const TreeScope* parent_tree_scope = node->GetTreeScope().ParentTreeScope();
  return parent_tree_scope ? &parent_tree_scope->RootNode() : 0;
}

unsigned short Internals::compareTreeScopePosition(
    const Node* node1,
    const Node* node2,
    ExceptionState& exception_state) const {
  DCHECK(node1 && node2);
  const TreeScope* tree_scope1 =
      node1->IsDocumentNode()
          ? static_cast<const TreeScope*>(ToDocument(node1))
          : node1->IsShadowRoot()
                ? static_cast<const TreeScope*>(ToShadowRoot(node1))
                : 0;
  const TreeScope* tree_scope2 =
      node2->IsDocumentNode()
          ? static_cast<const TreeScope*>(ToDocument(node2))
          : node2->IsShadowRoot()
                ? static_cast<const TreeScope*>(ToShadowRoot(node2))
                : 0;
  if (!tree_scope1 || !tree_scope2) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        String::Format(
            "The %s node is neither a document node, nor a shadow root.",
            tree_scope1 ? "second" : "first"));
    return 0;
  }
  return tree_scope1->ComparePosition(*tree_scope2);
}

void Internals::pauseAnimations(double pause_time,
                                ExceptionState& exception_state) {
  if (pause_time < 0) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, ExceptionMessages::IndexExceedsMinimumBound(
                                 "pauseTime", pause_time, 0.0));
    return;
  }

  if (!GetFrame())
    return;

  GetFrame()->View()->UpdateAllLifecyclePhases();
  GetFrame()->GetDocument()->Timeline().PauseAnimationsForTesting(pause_time);
}

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 delta_time_in_seconds,
                                    ExceptionState& exception_state) {
  DCHECK(image);
  if (delta_time_in_seconds < 0) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        ExceptionMessages::IndexExceedsMinimumBound(
            "deltaTimeInSeconds", delta_time_in_seconds, 0.0));
    return;
  }

  ImageResourceContent* resource = nullptr;
  if (isHTMLImageElement(*image)) {
    resource = toHTMLImageElement(*image).CachedImage();
  } else if (isSVGImageElement(*image)) {
    resource = toSVGImageElement(*image).CachedImage();
  } else {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The element provided is not a image element.");
    return;
  }

  if (!resource || !resource->HasImage()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The image resource is not available.");
    return;
  }

  Image* image_data = resource->GetImage();
  if (!image_data->IsBitmapImage()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The image resource is not a BitmapImage type.");
    return;
  }

  image_data->AdvanceTime(delta_time_in_seconds);
}

void Internals::advanceImageAnimation(Element* image,
                                      ExceptionState& exception_state) {
  DCHECK(image);

  ImageResourceContent* resource = nullptr;
  if (isHTMLImageElement(*image)) {
    resource = toHTMLImageElement(*image).CachedImage();
  } else if (isSVGImageElement(*image)) {
    resource = toSVGImageElement(*image).CachedImage();
  } else {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The element provided is not a image element.");
    return;
  }

  if (!resource || !resource->HasImage()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The image resource is not available.");
    return;
  }

  Image* image_data = resource->GetImage();
  image_data->AdvanceAnimationForTesting();
}

bool Internals::hasShadowInsertionPoint(const Node* root,
                                        ExceptionState& exception_state) const {
  DCHECK(root);
  if (!root->IsShadowRoot()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The node argument is not a shadow root.");
    return false;
  }
  return ToShadowRoot(root)->ContainsShadowElements();
}

bool Internals::hasContentElement(const Node* root,
                                  ExceptionState& exception_state) const {
  DCHECK(root);
  if (!root->IsShadowRoot()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The node argument is not a shadow root.");
    return false;
  }
  return ToShadowRoot(root)->ContainsContentElements();
}

size_t Internals::countElementShadow(const Node* root,
                                     ExceptionState& exception_state) const {
  DCHECK(root);
  if (!root->IsShadowRoot()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The node argument is not a shadow root.");
    return 0;
  }
  return ToShadowRoot(root)->ChildShadowRootCount();
}

Node* Internals::nextSiblingInFlatTree(Node* node,
                                       ExceptionState& exception_state) {
  DCHECK(node);
  if (!node->CanParticipateInFlatTree()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "The node argument doesn't particite in the flat tree.");
    return 0;
  }
  return FlatTreeTraversal::NextSibling(*node);
}

Node* Internals::firstChildInFlatTree(Node* node,
                                      ExceptionState& exception_state) {
  DCHECK(node);
  if (!node->CanParticipateInFlatTree()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "The node argument doesn't particite in the flat tree");
    return 0;
  }
  return FlatTreeTraversal::FirstChild(*node);
}

Node* Internals::lastChildInFlatTree(Node* node,
                                     ExceptionState& exception_state) {
  DCHECK(node);
  if (!node->CanParticipateInFlatTree()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "The node argument doesn't particite in the flat tree.");
    return 0;
  }
  return FlatTreeTraversal::LastChild(*node);
}

Node* Internals::nextInFlatTree(Node* node, ExceptionState& exception_state) {
  DCHECK(node);
  if (!node->CanParticipateInFlatTree()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "The node argument doesn't particite in the flat tree.");
    return 0;
  }
  return FlatTreeTraversal::Next(*node);
}

Node* Internals::previousInFlatTree(Node* node,
                                    ExceptionState& exception_state) {
  DCHECK(node);
  if (!node->CanParticipateInFlatTree()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "The node argument doesn't particite in the flat tree.");
    return 0;
  }
  return FlatTreeTraversal::Previous(*node);
}

String Internals::elementLayoutTreeAsText(Element* element,
                                          ExceptionState& exception_state) {
  DCHECK(element);
  element->GetDocument().View()->UpdateAllLifecyclePhases();

  String representation = ExternalRepresentation(element);
  if (representation.IsEmpty()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "The element provided has no external representation.");
    return String();
  }

  return representation;
}

CSSStyleDeclaration* Internals::computedStyleIncludingVisitedInfo(
    Node* node) const {
  DCHECK(node);
  bool allow_visited_style = true;
  return CSSComputedStyleDeclaration::Create(node, allow_visited_style);
}

ShadowRoot* Internals::createUserAgentShadowRoot(Element* host) {
  DCHECK(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) {
  DCHECK(host);
  if (ElementShadow* shadow = host->Shadow())
    return &shadow->YoungestShadowRoot();
  return 0;
}

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

ShadowRoot* Internals::youngerShadowRoot(Node* shadow,
                                         ExceptionState& exception_state) {
  DCHECK(shadow);
  if (!shadow->IsShadowRoot()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The node provided is not a shadow root.");
    return 0;
  }

  return ToShadowRoot(shadow)->YoungerShadowRoot();
}

String Internals::shadowRootType(const Node* root,
                                 ExceptionState& exception_state) const {
  DCHECK(root);
  if (!root->IsShadowRoot()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The node provided is not a shadow root.");
    return String();
  }

  switch (ToShadowRoot(root)->GetType()) {
    case ShadowRootType::kUserAgent:
      return String("UserAgentShadowRoot");
    case ShadowRootType::V0:
      return String("V0ShadowRoot");
    case ShadowRootType::kOpen:
      return String("OpenShadowRoot");
    case ShadowRootType::kClosed:
      return String("ClosedShadowRoot");
    default:
      NOTREACHED();
      return String("Unknown");
  }
}

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

String Internals::visiblePlaceholder(Element* element) {
  if (element && IsTextControlElement(*element)) {
    const TextControlElement& text_control_element =
        ToTextControlElement(*element);
    if (!text_control_element.IsPlaceholderVisible())
      return String();
    if (HTMLElement* placeholder_element =
            text_control_element.PlaceholderElement())
      return placeholder_element->textContent();
  }

  return String();
}

void Internals::selectColorInColorChooser(Element* element,
                                          const String& color_value) {
  DCHECK(element);
  if (!isHTMLInputElement(*element))
    return;
  Color color;
  if (!color.SetFromString(color_value))
    return;
  toHTMLInputElement(*element).SelectColorInColorChooser(color);
}

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

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

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

Vector<String> Internals::formControlStateOfHistoryItem(
    ExceptionState& exception_state) {
  HistoryItem* main_item = nullptr;
  if (GetFrame())
    main_item = GetFrame()->Loader().GetDocumentLoader()->GetHistoryItem();
  if (!main_item) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "No history item is available.");
    return Vector<String>();
  }
  return main_item->GetDocumentState();
}

void Internals::setFormControlStateOfHistoryItem(
    const Vector<String>& state,
    ExceptionState& exception_state) {
  HistoryItem* main_item = nullptr;
  if (GetFrame())
    main_item = GetFrame()->Loader().GetDocumentLoader()->GetHistoryItem();
  if (!main_item) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "No history item is available.");
    return;
  }
  main_item->ClearDocumentState();
  main_item->SetDocumentState(state);
}

DOMWindow* Internals::pagePopupWindow() const {
  if (!document_)
    return nullptr;
  if (Page* page = document_->GetPage()) {
    LocalDOMWindow* popup =
        ToLocalDOMWindow(page->GetChromeClient().PagePopupWindowForTesting());
    if (popup) {
      // We need to make the popup same origin so layout tests can access it.
      popup->document()->UpdateSecurityOrigin(document_->GetSecurityOrigin());
    }
    return popup;
  }
  return nullptr;
}

ClientRect* Internals::absoluteCaretBounds(ExceptionState& exception_state) {
  if (!GetFrame()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The document's frame cannot be retrieved.");
    return ClientRect::Create();
  }

  document_->UpdateStyleAndLayoutIgnorePendingStylesheets();
  return ClientRect::Create(GetFrame()->Selection().AbsoluteCaretBounds());
}

String Internals::textAffinity() {
  if (GetFrame()
          ->GetPage()
          ->GetFocusController()
          .FocusedFrame()
          ->Selection()
          .GetSelectionInDOMTree()
          .Affinity() == TextAffinity::kUpstream) {
    return "Upstream";
  }
  return "Downstream";
}

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

  element->GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
  LayoutObject* layout_object = element->GetLayoutObject();
  if (!layout_object)
    return ClientRect::Create();
  return ClientRect::Create(
      layout_object->AbsoluteBoundingBoxRectIgnoringTransforms());
}

void Internals::setMarker(Document* document,
                          const Range* range,
                          const String& marker_type,
                          ExceptionState& exception_state) {
  if (!document) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "No context document is available.");
    return;
  }

  WTF::Optional<DocumentMarker::MarkerType> type = MarkerTypeFrom(marker_type);
  if (!type) {
    exception_state.ThrowDOMException(
        kSyntaxError,
        "The marker type provided ('" + marker_type + "') is invalid.");
    return;
  }

  if (type != DocumentMarker::kSpelling && type != DocumentMarker::kGrammar) {
    exception_state.ThrowDOMException(kSyntaxError,
                                      "internals.setMarker() currently only "
                                      "supports spelling and grammar markers; "
                                      "attempted to add marker of type '" +
                                          marker_type + "'.");
    return;
  }

  document->UpdateStyleAndLayoutIgnorePendingStylesheets();
  if (type == DocumentMarker::kSpelling) {
    document->Markers().AddSpellingMarker(range->StartPosition(),
                                          range->EndPosition());
  } else {
    document->Markers().AddGrammarMarker(range->StartPosition(),
                                         range->EndPosition());
  }
}

unsigned Internals::markerCountForNode(Node* node,
                                       const String& marker_type,
                                       ExceptionState& exception_state) {
  DCHECK(node);
  WTF::Optional<DocumentMarker::MarkerTypes> marker_types =
      MarkerTypesFrom(marker_type);
  if (!marker_types) {
    exception_state.ThrowDOMException(
        kSyntaxError,
        "The marker type provided ('" + marker_type + "') is invalid.");
    return 0;
  }

  return node->GetDocument()
      .Markers()
      .MarkersFor(node, marker_types.value())
      .size();
}

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

  // Only TextMatch markers can be active.
  DocumentMarker::MarkerType marker_type = DocumentMarker::kTextMatch;
  DocumentMarkerVector markers =
      node->GetDocument().Markers().MarkersFor(node, marker_type);

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

  return active_marker_count;
}

DocumentMarker* Internals::MarkerAt(Node* node,
                                    const String& marker_type,
                                    unsigned index,
                                    ExceptionState& exception_state) {
  DCHECK(node);
  WTF::Optional<DocumentMarker::MarkerTypes> marker_types =
      MarkerTypesFrom(marker_type);
  if (!marker_types) {
    exception_state.ThrowDOMException(
        kSyntaxError,
        "The marker type provided ('" + marker_type + "') is invalid.");
    return 0;
  }

  DocumentMarkerVector markers =
      node->GetDocument().Markers().MarkersFor(node, marker_types.value());
  if (markers.size() <= index)
    return 0;
  return markers[index];
}

Range* Internals::markerRangeForNode(Node* node,
                                     const String& marker_type,
                                     unsigned index,
                                     ExceptionState& exception_state) {
  DCHECK(node);
  DocumentMarker* marker = MarkerAt(node, marker_type, index, exception_state);
  if (!marker)
    return nullptr;
  return Range::Create(node->GetDocument(), node, marker->StartOffset(), node,
                       marker->EndOffset());
}

String Internals::markerDescriptionForNode(Node* node,
                                           const String& marker_type,
                                           unsigned index,
                                           ExceptionState& exception_state) {
  DocumentMarker* marker = MarkerAt(node, marker_type, index, exception_state);
  if (!marker)
    return String();
  return marker->Description();
}

static WTF::Optional<DocumentMarker::MatchStatus> MatchStatusFrom(
    const String& match_status) {
  if (EqualIgnoringASCIICase(match_status, "kActive"))
    return DocumentMarker::MatchStatus::kActive;
  if (EqualIgnoringASCIICase(match_status, "kInactive"))
    return DocumentMarker::MatchStatus::kInactive;
  return WTF::nullopt;
}

void Internals::addTextMatchMarker(const Range* range,
                                   const String& match_status,
                                   ExceptionState& exception_state) {
  DCHECK(range);
  if (!range->OwnerDocument().View())
    return;

  WTF::Optional<DocumentMarker::MatchStatus> match_status_enum =
      MatchStatusFrom(match_status);
  if (!match_status_enum) {
    exception_state.ThrowDOMException(
        kSyntaxError,
        "The match status provided ('" + match_status + "') is invalid.");
    return;
  }

  range->OwnerDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
  range->OwnerDocument().Markers().AddTextMatchMarker(
      EphemeralRange(range), match_status_enum.value());

  // This simulates what the production code does after
  // DocumentMarkerController::addTextMatchMarker().
  range->OwnerDocument().View()->InvalidatePaintForTickmarks();
}

static bool ParseColor(const String& value,
                       Color& color,
                       ExceptionState& exception_state,
                       String error_message) {
  if (!color.SetFromString(value)) {
    exception_state.ThrowDOMException(kInvalidAccessError, error_message);
    return false;
  }
  return true;
}

void Internals::addCompositionMarker(const Range* range,
                                     const String& underline_color_value,
                                     bool thick,
                                     const String& background_color_value,
                                     ExceptionState& exception_state) {
  DCHECK(range);
  range->OwnerDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();

  Color underline_color;
  Color background_color;
  if (ParseColor(underline_color_value, underline_color, exception_state,
                 "Invalid underline color.") &&
      ParseColor(background_color_value, background_color, exception_state,
                 "Invalid background color.")) {
    range->OwnerDocument().Markers().AddCompositionMarker(
        EphemeralRange(range), underline_color, thick, background_color);
  }
}

void Internals::setTextMatchMarkersActive(Node* node,
                                          unsigned start_offset,
                                          unsigned end_offset,
                                          bool active) {
  DCHECK(node);
  node->GetDocument().Markers().SetTextMatchMarkersActive(node, start_offset,
                                                          end_offset, active);
}

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

  document->GetFrame()->GetEditor().SetMarkedTextMatchesAreHighlighted(
      highlight);
}

void Internals::setFrameViewPosition(Document* document,
                                     long x,
                                     long y,
                                     ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->View()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return;
  }

  FrameView* frame_view = document->View();
  bool scrollbars_suppressed_old_value = frame_view->ScrollbarsSuppressed();

  frame_view->SetScrollbarsSuppressed(false);
  frame_view->UpdateScrollOffsetFromInternals(IntSize(x, y));
  frame_view->SetScrollbarsSuppressed(scrollbars_suppressed_old_value);
}

String Internals::viewportAsText(Document* document,
                                 float,
                                 int available_width,
                                 int available_height,
                                 ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->GetPage()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return String();
  }

  document->UpdateStyleAndLayoutIgnorePendingStylesheets();

  Page* page = document->GetPage();

  // Update initial viewport size.
  IntSize initial_viewport_size(available_width, available_height);
  document->GetPage()->DeprecatedLocalMainFrame()->View()->SetFrameRect(
      IntRect(IntPoint::Zero(), initial_viewport_size));

  ViewportDescription description = page->GetViewportDescription();
  PageScaleConstraints constraints =
      description.Resolve(FloatSize(initial_viewport_size), Length());

  constraints.FitToContentsWidth(constraints.layout_size.Width(),
                                 available_width);
  constraints.ResolveAutoInitialScale();

  StringBuilder builder;

  builder.Append("viewport size ");
  builder.Append(String::Number(constraints.layout_size.Width()));
  builder.Append('x');
  builder.Append(String::Number(constraints.layout_size.Height()));

  builder.Append(" scale ");
  builder.Append(String::Number(constraints.initial_scale));
  builder.Append(" with limits [");
  builder.Append(String::Number(constraints.minimum_scale));
  builder.Append(", ");
  builder.Append(String::Number(constraints.maximum_scale));

  builder.Append("] and userScalable ");
  builder.Append(description.user_zoom ? "true" : "false");

  return builder.ToString();
}

bool Internals::elementShouldAutoComplete(Element* element,
                                          ExceptionState& exception_state) {
  DCHECK(element);
  if (isHTMLInputElement(*element))
    return toHTMLInputElement(*element).ShouldAutocomplete();

  exception_state.ThrowDOMException(kInvalidNodeTypeError,
                                    "The element provided is not an INPUT.");
  return false;
}

String Internals::suggestedValue(Element* element,
                                 ExceptionState& exception_state) {
  DCHECK(element);
  if (!element->IsFormControlElement()) {
    exception_state.ThrowDOMException(
        kInvalidNodeTypeError,
        "The element provided is not a form control element.");
    return String();
  }

  String suggested_value;
  if (isHTMLInputElement(*element))
    suggested_value = toHTMLInputElement(*element).SuggestedValue();

  if (isHTMLTextAreaElement(*element))
    suggested_value = toHTMLTextAreaElement(*element).SuggestedValue();

  if (isHTMLSelectElement(*element))
    suggested_value = toHTMLSelectElement(*element).SuggestedValue();

  return suggested_value;
}

void Internals::setSuggestedValue(Element* element,
                                  const String& value,
                                  ExceptionState& exception_state) {
  DCHECK(element);
  if (!element->IsFormControlElement()) {
    exception_state.ThrowDOMException(
        kInvalidNodeTypeError,
        "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& exception_state) {
  DCHECK(element);
  if (!isHTMLInputElement(*element)) {
    exception_state.ThrowDOMException(kInvalidNodeTypeError,
                                      "The element provided is not an INPUT.");
    return;
  }

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

void Internals::setAutofilled(Element* element,
                              bool enabled,
                              ExceptionState& exception_state) {
  DCHECK(element);
  if (!element->IsFormControlElement()) {
    exception_state.ThrowDOMException(
        kInvalidNodeTypeError,
        "The element provided is not a form control element.");
    return;
  }
  ToHTMLFormControlElement(element)->SetAutofilled(enabled);
}

Range* Internals::rangeFromLocationAndLength(Element* scope,
                                             int range_location,
                                             int range_length) {
  DCHECK(scope);

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

  return CreateRange(
      PlainTextRange(range_location, range_location + range_length)
          .CreateRange(*scope));
}

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

  return PlainTextRange::Create(*scope, *range).Start();
}

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

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

String Internals::rangeAsText(const Range* range) {
  DCHECK(range);
  // Clean layout is required by plain text extraction.
  range->OwnerDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();

  return range->GetText();
}

// 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& exception_state) {
  DCHECK(document);
  if (!document->GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return 0;
  }

  document->UpdateStyleAndLayout();

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

  EventHandler& event_handler = document->GetFrame()->GetEventHandler();
  IntPoint hit_test_point =
      document->GetFrame()->View()->RootFrameToContents(point);
  HitTestResult result = event_handler.HitTestResultAtPoint(
      hit_test_point,
      HitTestRequest::kReadOnly | HitTestRequest::kActive |
          HitTestRequest::kListBased,
      LayoutSize(radius));

  Node* target_node = 0;
  IntPoint adjusted_point;

  bool found_node = event_handler.BestClickableNodeForHitTestResult(
      result, adjusted_point, target_node);
  if (found_node)
    return DOMPoint::Create(adjusted_point.X(), adjusted_point.Y());

  return 0;
}

Node* Internals::touchNodeAdjustedToBestClickableNode(
    long x,
    long y,
    long width,
    long height,
    Document* document,
    ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return 0;
  }

  document->UpdateStyleAndLayout();

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

  EventHandler& event_handler = document->GetFrame()->GetEventHandler();
  IntPoint hit_test_point =
      document->GetFrame()->View()->RootFrameToContents(point);
  HitTestResult result = event_handler.HitTestResultAtPoint(
      hit_test_point,
      HitTestRequest::kReadOnly | HitTestRequest::kActive |
          HitTestRequest::kListBased,
      LayoutSize(radius));

  Node* target_node = 0;
  IntPoint adjusted_point;
  document->GetFrame()->GetEventHandler().BestClickableNodeForHitTestResult(
      result, adjusted_point, target_node);
  return target_node;
}

DOMPoint* Internals::touchPositionAdjustedToBestContextMenuNode(
    long x,
    long y,
    long width,
    long height,
    Document* document,
    ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return 0;
  }

  document->UpdateStyleAndLayout();

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

  EventHandler& event_handler = document->GetFrame()->GetEventHandler();
  IntPoint hit_test_point =
      document->GetFrame()->View()->RootFrameToContents(point);
  HitTestResult result = event_handler.HitTestResultAtPoint(
      hit_test_point,
      HitTestRequest::kReadOnly | HitTestRequest::kActive |
          HitTestRequest::kListBased,
      LayoutSize(radius));

  Node* target_node = 0;
  IntPoint adjusted_point;

  bool found_node = event_handler.BestContextMenuNodeForHitTestResult(
      result, adjusted_point, target_node);
  if (found_node)
    return DOMPoint::Create(adjusted_point.X(), adjusted_point.Y());

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

Node* Internals::touchNodeAdjustedToBestContextMenuNode(
    long x,
    long y,
    long width,
    long height,
    Document* document,
    ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return 0;
  }

  document->UpdateStyleAndLayout();

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

  EventHandler& event_handler = document->GetFrame()->GetEventHandler();
  IntPoint hit_test_point =
      document->GetFrame()->View()->RootFrameToContents(point);
  HitTestResult result = event_handler.HitTestResultAtPoint(
      hit_test_point,
      HitTestRequest::kReadOnly | HitTestRequest::kActive |
          HitTestRequest::kListBased,
      LayoutSize(radius));

  Node* target_node = 0;
  IntPoint adjusted_point;
  event_handler.BestContextMenuNodeForHitTestResult(result, adjusted_point,
                                                    target_node);
  return target_node;
}

ClientRect* Internals::bestZoomableAreaForTouchPoint(
    long x,
    long y,
    long width,
    long height,
    Document* document,
    ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return nullptr;
  }

  document->UpdateStyleAndLayout();

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

  Node* target_node = 0;
  IntRect zoomable_area;
  bool found_node =
      document->GetFrame()->GetEventHandler().BestZoomableAreaForTouchPoint(
          point, radius, zoomable_area, target_node);
  if (found_node)
    return ClientRect::Create(zoomable_area);

  return nullptr;
}

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

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

  return requester->LastRequestSequence();
}

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

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

  return requester->LastProcessedSequence();
}

String Internals::idleTimeSpellCheckerState(Document* document,
                                            ExceptionState& exception_state) {
  static const char* const kTexts[] = {
#define V(state) #state,
      FOR_EACH_IDLE_SPELL_CHECK_CALLBACK_STATE(V)
#undef V
  };

  if (!document || !document->GetFrame()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "No frame can be obtained from the provided document.");
    return String();
  }

  IdleSpellCheckCallback::State state = document->GetFrame()
                                            ->GetSpellChecker()
                                            .GetIdleSpellCheckCallback()
                                            .GetState();
  const auto& it = std::begin(kTexts) + static_cast<size_t>(state);
  DCHECK_GE(it, std::begin(kTexts)) << "Unknown state value";
  DCHECK_LT(it, std::end(kTexts)) << "Unknown state value";
  return *it;
}

void Internals::runIdleTimeSpellChecker(Document* document,
                                        ExceptionState& exception_state) {
  if (!document || !document->GetFrame()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "No frame can be obtained from the provided document.");
    return;
  }

  document->GetFrame()
      ->GetSpellChecker()
      .GetIdleSpellCheckCallback()
      .ForceInvocationForTesting();
}

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> atomic_languages;
  for (size_t i = 0; i < languages.size(); ++i)
    atomic_languages.push_back(AtomicString(languages[i]));
  OverrideUserPreferredLanguages(atomic_languages);
}

unsigned Internals::mediaKeysCount() {
  return InstanceCounters::CounterValue(InstanceCounters::kMediaKeysCounter);
}

unsigned Internals::mediaKeySessionCount() {
  return InstanceCounters::CounterValue(
      InstanceCounters::kMediaKeySessionCounter);
}

unsigned Internals::suspendableObjectCount(Document* document) {
  DCHECK(document);
  return document->SuspendableObjectCount();
}

static unsigned EventHandlerCount(
    Document& document,
    EventHandlerRegistry::EventHandlerClass handler_class) {
  if (!document.GetPage())
    return 0;
  EventHandlerRegistry* registry =
      &document.GetPage()->GetEventHandlerRegistry();
  unsigned count = 0;
  const EventTargetSet* targets = registry->EventHandlerTargets(handler_class);
  if (targets) {
    for (const auto& target : *targets)
      count += target.value;
  }
  return count;
}

unsigned Internals::wheelEventHandlerCount(Document* document) {
  DCHECK(document);
  return EventHandlerCount(*document,
                           EventHandlerRegistry::kWheelEventBlocking);
}

unsigned Internals::scrollEventHandlerCount(Document* document) {
  DCHECK(document);
  return EventHandlerCount(*document, EventHandlerRegistry::kScrollEvent);
}

unsigned Internals::touchStartOrMoveEventHandlerCount(Document* document) {
  DCHECK(document);
  return EventHandlerCount(
             *document, EventHandlerRegistry::kTouchStartOrMoveEventBlocking) +
         EventHandlerCount(*document,
                           EventHandlerRegistry::kTouchStartOrMoveEventPassive);
}

unsigned Internals::touchEndOrCancelEventHandlerCount(Document* document) {
  DCHECK(document);
  return EventHandlerCount(
             *document, EventHandlerRegistry::kTouchEndOrCancelEventBlocking) +
         EventHandlerCount(*document,
                           EventHandlerRegistry::kTouchEndOrCancelEventPassive);
}

static PaintLayer* FindLayerForGraphicsLayer(PaintLayer* search_root,
                                             GraphicsLayer* graphics_layer,
                                             IntSize* layer_offset,
                                             String* layer_type) {
  *layer_offset = IntSize();
  if (search_root->HasCompositedLayerMapping() &&
      graphics_layer ==
          search_root->GetCompositedLayerMapping()->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 (!search_root->GetLayoutObject().HasTransformRelatedProperty() &&
        search_root->ScrollParent() &&
        search_root->Parent() == search_root->ScrollParent()) {
      *layer_type = "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 (search_root->GetLayoutObject().OffsetParent() ==
          search_root->Parent()->GetLayoutObject().OffsetParent()) {
        LayoutBoxModelObject& current = search_root->GetLayoutObject();
        LayoutBoxModelObject& parent = search_root->Parent()->GetLayoutObject();
        layer_offset->SetWidth((parent.OffsetLeft(parent.OffsetParent()) -
                                current.OffsetLeft(parent.OffsetParent()))
                                   .ToInt());
        layer_offset->SetHeight((parent.OffsetTop(parent.OffsetParent()) -
                                 current.OffsetTop(parent.OffsetParent()))
                                    .ToInt());
        return search_root->Parent();
      }
    }

    LayoutRect rect;
    PaintLayer::MapRectInPaintInvalidationContainerToBacking(
        search_root->GetLayoutObject(), rect);
    rect.Move(search_root->GetCompositedLayerMapping()
                  ->ContentOffsetInCompositingLayer());

    *layer_offset = IntSize(rect.X().ToInt(), rect.Y().ToInt());
    return search_root;
  }

  // If the |graphicsLayer| is a scroller's scrollingContent layer,
  // consider this is a scrolling layer.
  GraphicsLayer* layer_for_scrolling =
      search_root->GetScrollableArea()
          ? search_root->GetScrollableArea()->LayerForScrolling()
          : 0;
  if (graphics_layer == layer_for_scrolling) {
    *layer_type = "scrolling";
    return search_root;
  }

  if (search_root->GetCompositingState() == kPaintsIntoGroupedBacking) {
    GraphicsLayer* squashing_layer =
        search_root->GroupedMapping()->SquashingLayer();
    if (graphics_layer == squashing_layer) {
      *layer_type = "squashing";
      LayoutRect rect;
      PaintLayer::MapRectInPaintInvalidationContainerToBacking(
          search_root->GetLayoutObject(), rect);
      *layer_offset = IntSize(rect.X().ToInt(), rect.Y().ToInt());
      return search_root;
    }
  }

  GraphicsLayer* layer_for_horizontal_scrollbar =
      search_root->GetScrollableArea()
          ? search_root->GetScrollableArea()->LayerForHorizontalScrollbar()
          : 0;
  if (graphics_layer == layer_for_horizontal_scrollbar) {
    *layer_type = "horizontalScrollbar";
    return search_root;
  }

  GraphicsLayer* layer_for_vertical_scrollbar =
      search_root->GetScrollableArea()
          ? search_root->GetScrollableArea()->LayerForVerticalScrollbar()
          : 0;
  if (graphics_layer == layer_for_vertical_scrollbar) {
    *layer_type = "verticalScrollbar";
    return search_root;
  }

  GraphicsLayer* layer_for_scroll_corner =
      search_root->GetScrollableArea()
          ? search_root->GetScrollableArea()->LayerForScrollCorner()
          : 0;
  if (graphics_layer == layer_for_scroll_corner) {
    *layer_type = "scrollCorner";
    return search_root;
  }

  // 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 = search_root->LastChild(); child;
       child = child->PreviousSibling()) {
    PaintLayer* found_layer = FindLayerForGraphicsLayer(
        child, graphics_layer, layer_offset, layer_type);
    if (found_layer)
      return found_layer;
  }

  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* graphics_layer,
                                    LayerRectList* rects) {
  WebVector<blink::WebRect> layer_rects =
      graphics_layer->PlatformLayer()->TouchEventHandlerRegion();
  if (!layer_rects.empty()) {
    MergeRects(layer_rects);
    String layer_type;
    IntSize layer_offset;
    PaintLayer* paint_layer = FindLayerForGraphicsLayer(
        compositor->RootLayer(), graphics_layer, &layer_offset, &layer_type);
    Node* node = paint_layer ? paint_layer->GetLayoutObject().GetNode() : 0;
    for (size_t i = 0; i < layer_rects.size(); ++i) {
      if (!layer_rects[i].IsEmpty()) {
        rects->Append(node, layer_type, layer_offset.Width(),
                      layer_offset.Height(),
                      ClientRect::Create(layer_rects[i]));
      }
    }
  }

  size_t num_children = graphics_layer->Children().size();
  for (size_t i = 0; i < num_children; ++i)
    AccumulateLayerRectList(compositor, graphics_layer->Children()[i], rects);
}

LayerRectList* Internals::touchEventTargetLayerRects(
    Document* document,
    ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->View() || !document->GetPage() || document != document_) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return nullptr;
  }

  if (ScrollingCoordinator* scrolling_coordinator =
          document->GetPage()->GetScrollingCoordinator())
    scrolling_coordinator->UpdateAfterCompositingChangeIfNeeded();

  LayoutViewItem view = document->GetLayoutViewItem();
  if (!view.IsNull()) {
    if (PaintLayerCompositor* compositor = view.Compositor()) {
      if (GraphicsLayer* root_layer = compositor->RootGraphicsLayer()) {
        LayerRectList* rects = LayerRectList::Create();
        AccumulateLayerRectList(compositor, root_layer, rects);
        return rects;
      }
    }
  }

  return nullptr;
}

bool Internals::executeCommand(Document* document,
                               const String& name,
                               const String& value,
                               ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return false;
  }

  LocalFrame* frame = document->GetFrame();
  return frame->GetEditor().ExecuteCommand(name, value);
}

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

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

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

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

StaticNodeList* Internals::nodesFromRect(
    Document* document,
    int center_x,
    int center_y,
    unsigned top_padding,
    unsigned right_padding,
    unsigned bottom_padding,
    unsigned left_padding,
    bool ignore_clipping,
    bool allow_child_frame_content,
    ExceptionState& exception_state) const {
  DCHECK(document);
  if (!document->GetFrame() || !document->GetFrame()->View()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "No view can be obtained from the provided document.");
    return nullptr;
  }

  LocalFrame* frame = document->GetFrame();
  FrameView* frame_view = document->View();
  LayoutViewItem layout_view_item = document->GetLayoutViewItem();

  if (layout_view_item.IsNull())
    return nullptr;

  float zoom_factor = frame->PageZoomFactor();
  LayoutPoint point =
      LayoutPoint(FloatPoint(center_x * zoom_factor + frame_view->ScrollX(),
                             center_y * zoom_factor + frame_view->ScrollY()));

  HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kReadOnly |
                                                HitTestRequest::kActive |
                                                HitTestRequest::kListBased;
  if (ignore_clipping)
    hit_type |= HitTestRequest::kIgnoreClipping;
  if (allow_child_frame_content)
    hit_type |= HitTestRequest::kAllowChildFrameContent;

  HitTestRequest request(hit_type);

  // When ignoreClipping is false, this method returns null for coordinates
  // outside of the viewport.
  if (!request.IgnoreClipping() &&
      !frame_view->VisibleContentRect().Intersects(
          HitTestLocation::RectForPoint(point, top_padding, right_padding,
                                        bottom_padding, left_padding)))
    return nullptr;

  HeapVector<Member<Node>> matches;
  HitTestResult result(request, point, top_padding, right_padding,
                       bottom_padding, left_padding);
  layout_view_item.HitTest(result);
  CopyToVector(result.ListBasedTestResult(), matches);

  return StaticNodeList::Adopt(matches);
}

bool Internals::hasSpellingMarker(Document* document,
                                  int from,
                                  int length,
                                  ExceptionState& exception_state) {
  if (!document || !document->GetFrame()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "No frame can be obtained from the provided document.");
    return false;
  }

  document->UpdateStyleAndLayoutIgnorePendingStylesheets();
  return document->GetFrame()->GetSpellChecker().SelectionStartHasMarkerFor(
      DocumentMarker::kSpelling, from, length);
}

void Internals::setSpellCheckingEnabled(bool enabled,
                                        ExceptionState& exception_state) {
  if (!GetFrame()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "No frame can be obtained from the provided document.");
    return;
  }

  if (enabled != GetFrame()->GetSpellChecker().IsSpellCheckingEnabled())
    GetFrame()->GetSpellChecker().ToggleSpellCheckingEnabled();
}

void Internals::replaceMisspelled(Document* document,
                                  const String& replacement,
                                  ExceptionState& exception_state) {
  if (!document || !document->GetFrame()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "No frame can be obtained from the provided document.");
    return;
  }

  document->UpdateStyleAndLayoutIgnorePendingStylesheets();
  document->GetFrame()->GetSpellChecker().ReplaceMisspelledRange(replacement);
}

bool Internals::canHyphenate(const AtomicString& locale) {
  return LayoutLocale::ValueOrDefault(LayoutLocale::Get(locale))
      .GetHyphenation();
}

void Internals::setMockHyphenation(const AtomicString& locale) {
  LayoutLocale::SetHyphenationForTesting(locale, AdoptRef(new MockHyphenation));
}

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

  return document->GetFrame()->GetEditor().IsOverwriteModeEnabled();
}

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

  document->GetFrame()->GetEditor().ToggleOverwriteModeEnabled();
}

unsigned Internals::numberOfLiveNodes() const {
  return InstanceCounters::CounterValue(InstanceCounters::kNodeCounter);
}

unsigned Internals::numberOfLiveDocuments() const {
  return InstanceCounters::CounterValue(InstanceCounters::kDocumentCounter);
}

bool Internals::hasGrammarMarker(Document* document,
                                 int from,
                                 int length,
                                 ExceptionState& exception_state) {
  if (!document || !document->GetFrame()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        "No frame can be obtained from the provided document.");
    return false;
  }

  document->UpdateStyleAndLayoutIgnorePendingStylesheets();
  return document->GetFrame()->GetSpellChecker().SelectionStartHasMarkerFor(
      DocumentMarker::kGrammar, from, length);
}

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

  unsigned count = 0;
  LocalFrame* frame = document->GetFrame();
  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 page_number) {
  DCHECK(document);
  return document->IsPageBoxVisible(page_number);
}

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

String Internals::elementLayerTreeAsText(
    Element* element,
    ExceptionState& exception_state) const {
  DCHECK(element);
  FrameView* frame_view = element->GetDocument().View();
  frame_view->UpdateAllLifecyclePhases();

  return elementLayerTreeAsText(element, 0, exception_state);
}

bool Internals::scrollsWithRespectTo(Element* element1,
                                     Element* element2,
                                     ExceptionState& exception_state) {
  DCHECK(element1 && element2);
  element1->GetDocument().View()->UpdateAllLifecyclePhases();

  LayoutObject* layout_object1 = element1->GetLayoutObject();
  LayoutObject* layout_object2 = element2->GetLayoutObject();
  if (!layout_object1 || !layout_object1->IsBox()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        layout_object1
            ? "The first provided element's layoutObject is not a box."
            : "The first provided element has no layoutObject.");
    return false;
  }
  if (!layout_object2 || !layout_object2->IsBox()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        layout_object2
            ? "The second provided element's layoutObject is not a box."
            : "The second provided element has no layoutObject.");
    return false;
  }

  PaintLayer* layer1 = ToLayoutBox(layout_object1)->Layer();
  PaintLayer* layer2 = ToLayoutBox(layout_object2)->Layer();
  if (!layer1 || !layer2) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        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& exception_state) const {
  DCHECK(document);
  if (!document->GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return String();
  }

  document->View()->UpdateAllLifecyclePhases();

  return document->GetFrame()->LayerTreeAsText(flags);
}

String Internals::elementLayerTreeAsText(
    Element* element,
    unsigned flags,
    ExceptionState& exception_state) const {
  DCHECK(element);
  element->GetDocument().UpdateStyleAndLayout();

  LayoutObject* layout_object = element->GetLayoutObject();
  if (!layout_object || !layout_object->IsBox()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError,
        layout_object ? "The provided element's layoutObject is not a box."
                      : "The provided element has no layoutObject.");
    return String();
  }

  PaintLayer* layer = ToLayoutBox(layout_object)->Layer();
  if (!layer || !layer->HasCompositedLayerMapping() ||
      !layer->GetCompositedLayerMapping()->MainGraphicsLayer()) {
    // Don't raise exception in these cases which may be normally used in tests.
    return String();
  }

  return layer->GetCompositedLayerMapping()
      ->MainGraphicsLayer()
      ->LayerTreeAsText(flags);
}

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

String Internals::mainThreadScrollingReasons(
    Document* document,
    ExceptionState& exception_state) const {
  DCHECK(document);
  if (!document->GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return String();
  }

  document->GetFrame()->View()->UpdateAllLifecyclePhases();

  return document->GetFrame()->View()->MainThreadScrollingReasonsAsText();
}

ClientRectList* Internals::nonFastScrollableRects(
    Document* document,
    ExceptionState& exception_state) const {
  DCHECK(document);
  if (!document->GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return nullptr;
  }

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

  return page->NonFastScrollableRects(document->GetFrame());
}

void Internals::evictAllResources() const {
  GetMemoryCache()->EvictResources();
}

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

  return CounterValueForElement(element);
}

int Internals::pageNumber(Element* element,
                          float page_width,
                          float page_height,
                          ExceptionState& exception_state) {
  if (!element)
    return 0;

  if (page_width <= 0 || page_height <= 0) {
    exception_state.ThrowDOMException(
        kV8TypeError, "Page width and height must be larger than 0.");
    return 0;
  }

  return PrintContext::PageNumberForElement(element,
                                            FloatSize(page_width, page_height));
}

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

  for (auto& icon_url : icon_urls)
    array.push_back(icon_url.icon_url_.GetString());

  return array;
}

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

Vector<String> Internals::allIconURLs(Document* document) const {
  return IconURLs(document, kFavicon | kTouchIcon | kTouchPrecomposedIcon);
}

int Internals::numberOfPages(float page_width,
                             float page_height,
                             ExceptionState& exception_state) {
  if (!GetFrame())
    return -1;

  if (page_width <= 0 || page_height <= 0) {
    exception_state.ThrowDOMException(
        kV8TypeError, "Page width and height must be larger than 0.");
    return -1;
  }

  return PrintContext::NumberOfPages(GetFrame(),
                                     FloatSize(page_width, page_height));
}

String Internals::pageProperty(String property_name,
                               int page_number,
                               ExceptionState& exception_state) const {
  if (!GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "No frame is available.");
    return String();
  }

  return PrintContext::PageProperty(GetFrame(), property_name.Utf8().data(),
                                    page_number);
}

String Internals::pageSizeAndMarginsInPixels(
    int page_number,
    int width,
    int height,
    int margin_top,
    int margin_right,
    int margin_bottom,
    int margin_left,
    ExceptionState& exception_state) const {
  if (!GetFrame()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "No frame is available.");
    return String();
  }

  return PrintContext::PageSizeAndMarginsInPixels(
      GetFrame(), page_number, width, height, margin_top, margin_right,
      margin_bottom, margin_left);
}

float Internals::pageScaleFactor(ExceptionState& exception_state) {
  if (!document_->GetPage()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The document's page cannot be retrieved.");
    return 0;
  }
  Page* page = document_->GetPage();
  return page->GetVisualViewport().Scale();
}

void Internals::setPageScaleFactor(float scale_factor,
                                   ExceptionState& exception_state) {
  if (scale_factor <= 0)
    return;
  if (!document_->GetPage()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The document's page cannot be retrieved.");
    return;
  }
  Page* page = document_->GetPage();
  page->GetVisualViewport().SetScale(scale_factor);
}

void Internals::setPageScaleFactorLimits(float min_scale_factor,
                                         float max_scale_factor,
                                         ExceptionState& exception_state) {
  if (!document_->GetPage()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The document's page cannot be retrieved.");
    return;
  }

  Page* page = document_->GetPage();
  page->SetDefaultPageScaleLimits(min_scale_factor, max_scale_factor);
}

bool Internals::magnifyScaleAroundAnchor(float scale_factor, float x, float y) {
  if (!GetFrame())
    return false;

  return GetFrame()->GetPage()->GetVisualViewport().MagnifyScaleAroundAnchor(
      scale_factor, FloatPoint(x, y));
}

void Internals::setIsCursorVisible(Document* document,
                                   bool is_visible,
                                   ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->GetPage()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "No context document can be obtained.");
    return;
  }
  document->GetPage()->SetIsCursorVisible(is_visible);
}

String Internals::effectivePreload(HTMLMediaElement* media_element) {
  DCHECK(media_element);
  return media_element->EffectivePreload();
}

void Internals::mediaPlayerRemoteRouteAvailabilityChanged(
    HTMLMediaElement* media_element,
    bool available) {
  DCHECK(media_element);
  media_element->RemoteRouteAvailabilityChanged(
      available ? WebRemotePlaybackAvailability::kDeviceAvailable
                : WebRemotePlaybackAvailability::kSourceNotSupported);
}

void Internals::mediaPlayerPlayingRemotelyChanged(
    HTMLMediaElement* media_element,
    bool remote) {
  DCHECK(media_element);
  if (remote)
    media_element->ConnectedToRemoteDevice();
  else
    media_element->DisconnectedFromRemoteDevice();
}

void Internals::setMediaElementNetworkState(HTMLMediaElement* media_element,
                                            int state) {
  DCHECK(media_element);
  DCHECK(state >= WebMediaPlayer::NetworkState::kNetworkStateEmpty);
  DCHECK(state <= WebMediaPlayer::NetworkState::kNetworkStateDecodeError);
  media_element->SetNetworkState(
      static_cast<WebMediaPlayer::NetworkState>(state));
}

void Internals::setPersistent(HTMLVideoElement* video_element,
                              bool persistent) {
  DCHECK(video_element);
  video_element->OnBecamePersistentVideo(persistent);
}

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

void Internals::registerURLSchemeAsBypassingContentSecurityPolicy(
    const String& scheme,
    const Vector<String>& policy_areas) {
  uint32_t policy_areas_enum = SchemeRegistry::kPolicyAreaNone;
  for (const auto& policy_area : policy_areas) {
    if (policy_area == "img")
      policy_areas_enum |= SchemeRegistry::kPolicyAreaImage;
    else if (policy_area == "style")
      policy_areas_enum |= SchemeRegistry::kPolicyAreaStyle;
  }
  SchemeRegistry::RegisterURLSchemeAsBypassingContentSecurityPolicy(
      scheme, static_cast<SchemeRegistry::PolicyAreas>(policy_areas_enum));
}

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

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

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

RecordTest* Internals::recordTest() const {
  return RecordTest::Create();
}

SequenceTest* Internals::sequenceTest() const {
  return SequenceTest::create();
}

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

OriginTrialsTest* Internals::originTrialsTest() const {
  return OriginTrialsTest::Create();
}

CallbackFunctionTest* Internals::callbackFunctionTest() const {
  return CallbackFunctionTest::Create();
}

Vector<String> Internals::getReferencedFilePaths() const {
  if (!GetFrame())
    return Vector<String>();

  return GetFrame()
      ->Loader()
      .GetDocumentLoader()
      ->GetHistoryItem()
      ->GetReferencedFilePaths();
}

void Internals::startStoringCompositedLayerDebugInfo(
    Document* document,
    ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->View()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return;
  }

  FrameView* frame_view = document->View();
  frame_view->SetIsStoringCompositedLayerDebugInfo(true);
  frame_view->UpdateAllLifecyclePhases();
}

void Internals::stopStoringCompositedLayerDebugInfo(
    Document* document,
    ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->View()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return;
  }

  FrameView* frame_view = document->View();
  frame_view->SetIsStoringCompositedLayerDebugInfo(false);
  frame_view->UpdateAllLifecyclePhases();
}

void Internals::startTrackingRepaints(Document* document,
                                      ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->View()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return;
  }

  FrameView* frame_view = document->View();
  frame_view->UpdateAllLifecyclePhases();
  frame_view->SetTracksPaintInvalidations(true);
}

void Internals::stopTrackingRepaints(Document* document,
                                     ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->View()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return;
  }

  FrameView* frame_view = document->View();
  frame_view->UpdateAllLifecyclePhases();
  frame_view->SetTracksPaintInvalidations(false);
}

void Internals::updateLayoutIgnorePendingStylesheetsAndRunPostLayoutTasks(
    Node* node,
    ExceptionState& exception_state) {
  Document* document = nullptr;
  if (!node) {
    document = document_;
  } else if (node->IsDocumentNode()) {
    document = ToDocument(node);
  } else if (isHTMLIFrameElement(*node)) {
    document = toHTMLIFrameElement(*node).contentDocument();
  }

  if (!document) {
    exception_state.ThrowTypeError(
        "The node provided is neither a document nor an IFrame.");
    return;
  }
  document->UpdateStyleAndLayoutIgnorePendingStylesheets(
      Document::kRunPostLayoutTasksSynchronously);
}

void Internals::forceFullRepaint(Document* document,
                                 ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->View()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return;
  }

  LayoutViewItem layout_view_item = document->GetLayoutViewItem();
  if (!layout_view_item.IsNull())
    layout_view_item.InvalidatePaintForViewAndCompositedLayers();
}

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

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

ClientRectList* Internals::AnnotatedRegions(Document* document,
                                            bool draggable,
                                            ExceptionState& exception_state) {
  DCHECK(document);
  if (!document->View()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "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.push_back(FloatQuad(FloatRect(regions[i].bounds)));
  }
  return ClientRectList::Create(quads);
}

static const char* CursorTypeToString(Cursor::Type cursor_type) {
  switch (cursor_type) {
    case Cursor::kPointer:
      return "Pointer";
    case Cursor::kCross:
      return "Cross";
    case Cursor::kHand:
      return "Hand";
    case Cursor::kIBeam:
      return "IBeam";
    case Cursor::kWait:
      return "Wait";
    case Cursor::kHelp:
      return "Help";
    case Cursor::kEastResize:
      return "EastResize";
    case Cursor::kNorthResize:
      return "NorthResize";
    case Cursor::kNorthEastResize:
      return "NorthEastResize";
    case Cursor::kNorthWestResize:
      return "NorthWestResize";
    case Cursor::kSouthResize:
      return "SouthResize";
    case Cursor::kSouthEastResize:
      return "SouthEastResize";
    case Cursor::kSouthWestResize:
      return "SouthWestResize";
    case Cursor::kWestResize:
      return "WestResize";
    case Cursor::kNorthSouthResize:
      return "NorthSouthResize";
    case Cursor::kEastWestResize:
      return "EastWestResize";
    case Cursor::kNorthEastSouthWestResize:
      return "NorthEastSouthWestResize";
    case Cursor::kNorthWestSouthEastResize:
      return "NorthWestSouthEastResize";
    case Cursor::kColumnResize:
      return "ColumnResize";
    case Cursor::kRowResize:
      return "RowResize";
    case Cursor::kMiddlePanning:
      return "MiddlePanning";
    case Cursor::kEastPanning:
      return "EastPanning";
    case Cursor::kNorthPanning:
      return "NorthPanning";
    case Cursor::kNorthEastPanning:
      return "NorthEastPanning";
    case Cursor::kNorthWestPanning:
      return "NorthWestPanning";
    case Cursor::kSouthPanning:
      return "SouthPanning";
    case Cursor::kSouthEastPanning:
      return "SouthEastPanning";
    case Cursor::kSouthWestPanning:
      return "SouthWestPanning";
    case Cursor::kWestPanning:
      return "WestPanning";
    case Cursor::kMove:
      return "Move";
    case Cursor::kVerticalText:
      return "VerticalText";
    case Cursor::kCell:
      return "Cell";
    case Cursor::kContextMenu:
      return "ContextMenu";
    case Cursor::kAlias:
      return "Alias";
    case Cursor::kProgress:
      return "Progress";
    case Cursor::kNoDrop:
      return "NoDrop";
    case Cursor::kCopy:
      return "Copy";
    case Cursor::kNone:
      return "None";
    case Cursor::kNotAllowed:
      return "NotAllowed";
    case Cursor::kZoomIn:
      return "ZoomIn";
    case Cursor::kZoomOut:
      return "ZoomOut";
    case Cursor::kGrab:
      return "Grab";
    case Cursor::kGrabbing:
      return "Grabbing";
    case Cursor::kCustom:
      return "Custom";
  }

  NOTREACHED();
  return "UNKNOWN";
}

String Internals::getCurrentCursorInfo() {
  if (!GetFrame())
    return String();

  Cursor cursor =
      GetFrame()->GetPage()->GetChromeClient().LastSetCursorForTesting();

  StringBuilder result;
  result.Append("type=");
  result.Append(CursorTypeToString(cursor.GetType()));
  result.Append(" hotSpot=");
  result.AppendNumber(cursor.HotSpot().X());
  result.Append(',');
  result.AppendNumber(cursor.HotSpot().Y());
  if (cursor.GetImage()) {
    IntSize size = cursor.GetImage()->Size();
    result.Append(" image=");
    result.AppendNumber(size.Width());
    result.Append('x');
    result.AppendNumber(size.Height());
  }
  if (cursor.ImageScaleFactor() != 1) {
    result.Append(" scale=");
    result.AppendNumber(cursor.ImageScaleFactor(), 8);
  }

  return result.ToString();
}

bool Internals::cursorUpdatePending() const {
  if (!GetFrame())
    return false;

  return GetFrame()->GetEventHandler().CursorUpdatePending();
}

DOMArrayBuffer* Internals::serializeObject(
    PassRefPtr<SerializedScriptValue> value) const {
  StringView view = value->GetWireData();
  DCHECK(view.Is8Bit());
  DOMArrayBuffer* buffer =
      DOMArrayBuffer::CreateUninitializedOrNull(view.length(), sizeof(LChar));
  if (buffer)
    memcpy(buffer->Data(), view.Characters8(), view.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);
}

DOMArrayBuffer* Internals::serializeWithInlineWasm(ScriptValue value) const {
  v8::Isolate* isolate = value.GetIsolate();
  ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
                                 "Internals", "serializeWithInlineWasm");
  v8::Local<v8::Value> v8_value = value.V8Value();
  SerializedScriptValue::SerializeOptions options;
  options.wasm_policy = SerializedScriptValue::SerializeOptions::kSerialize;
  RefPtr<SerializedScriptValue> obj = SerializedScriptValue::Serialize(
      isolate, v8_value, options, exception_state);
  if (exception_state.HadException())
    return nullptr;
  return serializeObject(obj);
}

ScriptValue Internals::deserializeBufferContainingWasm(
    ScriptState* state,
    DOMArrayBuffer* buffer) const {
  String value(static_cast<const UChar*>(buffer->Data()),
               buffer->ByteLength() / sizeof(UChar));
  DummyExceptionStateForTesting exception_state;
  SerializedScriptValue::DeserializeOptions options;
  options.read_wasm_from_stream = true;
  return ScriptValue::From(state,
                           SerializedScriptValue::Create(value)->Deserialize(
                               state->GetIsolate(), options));
}

void Internals::forceReload(bool bypass_cache) {
  if (!GetFrame())
    return;

  GetFrame()->Reload(
      bypass_cache ? kFrameLoadTypeReloadBypassingCache : kFrameLoadTypeReload,
      ClientRedirectPolicy::kNotClientRedirect);
}

Node* Internals::visibleSelectionAnchorNode() {
  if (!GetFrame())
    return nullptr;
  Position position = GetFrame()
                          ->Selection()
                          .ComputeVisibleSelectionInDOMTreeDeprecated()
                          .Base();
  return position.IsNull() ? nullptr : position.ComputeContainerNode();
}

unsigned Internals::visibleSelectionAnchorOffset() {
  if (!GetFrame())
    return 0;
  Position position = GetFrame()
                          ->Selection()
                          .ComputeVisibleSelectionInDOMTreeDeprecated()
                          .Base();
  return position.IsNull() ? 0 : position.ComputeOffsetInContainerNode();
}

Node* Internals::visibleSelectionFocusNode() {
  if (!GetFrame())
    return nullptr;
  Position position = GetFrame()
                          ->Selection()
                          .ComputeVisibleSelectionInDOMTreeDeprecated()
                          .Extent();
  return position.IsNull() ? nullptr : position.ComputeContainerNode();
}

unsigned Internals::visibleSelectionFocusOffset() {
  if (!GetFrame())
    return 0;
  Position position = GetFrame()
                          ->Selection()
                          .ComputeVisibleSelectionInDOMTreeDeprecated()
                          .Extent();
  return position.IsNull() ? 0 : position.ComputeOffsetInContainerNode();
}

ClientRect* Internals::selectionBounds(ExceptionState& exception_state) {
  if (!GetFrame()) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The document's frame cannot be retrieved.");
    return nullptr;
  }

  return ClientRect::Create(FloatRect(GetFrame()->Selection().Bounds()));
}

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

String Internals::getImageSourceURL(Element* element) {
  DCHECK(element);
  return element->ImageSourceURL();
}

void Internals::forceImageReload(Element* element,
                                 ExceptionState& exception_state) {
  if (!element || !isHTMLImageElement(*element)) {
    exception_state.ThrowDOMException(
        kInvalidAccessError, "The element should be HTMLImageElement.");
  }

  toHTMLImageElement(*element).ForceReload();
}

String Internals::selectMenuListText(HTMLSelectElement* select) {
  DCHECK(select);
  LayoutObject* layout_object = select->GetLayoutObject();
  if (!layout_object || !layout_object->IsMenuList())
    return String();

  LayoutMenuListItem menu_list_item =
      LayoutMenuListItem(ToLayoutMenuList(layout_object));
  return menu_list_item.GetText();
}

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

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

  HTMLSelectElement& select = toHTMLSelectElement(*node);
  if (item_index < 0 ||
      static_cast<size_t>(item_index) >= select.GetListItems().size())
    return false;
  const ComputedStyle* item_style =
      select.ItemComputedStyle(*select.GetListItems()[item_index]);
  return item_style && item_style->Direction() == TextDirection::kRtl;
}

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

  HTMLSelectElement& select = toHTMLSelectElement(*node);
  if (item_index < 0 ||
      static_cast<size_t>(item_index) >= select.GetListItems().size())
    return false;
  const ComputedStyle* item_style =
      select.ItemComputedStyle(*select.GetListItems()[item_index]);

  if (item_style) {
    const SimpleFontData* font_data = item_style->GetFont().PrimaryFont();
    DCHECK(font_data);
    return font_data ? font_data->GetFontMetrics().Height() : 0;
  }
  return 0;
}

void Internals::resetTypeAheadSession(HTMLSelectElement* select) {
  DCHECK(select);
  select->ResetTypeAheadSessionForTesting();
}

bool Internals::loseSharedGraphicsContext3D() {
  std::unique_ptr<WebGraphicsContext3DProvider> shared_provider =
      Platform::Current()->CreateSharedOffscreenGraphicsContext3DProvider();
  if (!shared_provider)
    return false;
  gpu::gles2::GLES2Interface* shared_gl = shared_provider->ContextGL();
  shared_gl->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).
  shared_gl->Finish();
  return true;
}

void Internals::forceCompositingUpdate(Document* document,
                                       ExceptionState& exception_state) {
  DCHECK(document);
  if (document->GetLayoutViewItem().IsNull()) {
    exception_state.ThrowDOMException(kInvalidAccessError,
                                      "The document provided is invalid.");
    return;
  }

  document->GetFrame()->View()->UpdateAllLifecyclePhases();
}

void Internals::setZoomFactor(float factor) {
  if (!GetFrame())
    return;

  GetFrame()->SetPageZoomFactor(factor);
}

void Internals::setShouldRevealPassword(Element* element,
                                        bool reveal,
                                        ExceptionState& exception_state) {
  DCHECK(element);
  if (!isHTMLInputElement(element)) {
    exception_state.ThrowDOMException(kInvalidNodeTypeError,
                                      "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* script_state) {
    AddOneFunction* self = new AddOneFunction(script_state);
    return self->BindToV8Function();
  }

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

  ScriptValue Call(ScriptValue value) override {
    v8::Local<v8::Value> v8_value = value.V8Value();
    DCHECK(v8_value->IsNumber());
    int int_value = v8_value.As<v8::Integer>()->Value();
    return ScriptValue(
        GetScriptState(),
        v8::Integer::New(GetScriptState()->GetIsolate(), int_value + 1));
  }
};

}  // namespace

ScriptPromise Internals::createResolvedPromise(ScriptState* script_state,
                                               ScriptValue value) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  resolver->Resolve(value);
  return promise;
}

ScriptPromise Internals::createRejectedPromise(ScriptState* script_state,
                                               ScriptValue value) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  resolver->Reject(value);
  return promise;
}

ScriptPromise Internals::addOneToPromise(ScriptState* script_state,
                                         ScriptPromise promise) {
  return promise.Then(AddOneFunction::CreateFunction(script_state));
}

ScriptPromise Internals::promiseCheck(ScriptState* script_state,
                                      long arg1,
                                      bool arg2,
                                      const Dictionary& arg3,
                                      const String& arg4,
                                      const Vector<String>& arg5,
                                      ExceptionState& exception_state) {
  if (arg2)
    return ScriptPromise::Cast(script_state,
                               V8String(script_state->GetIsolate(), "done"));
  exception_state.ThrowDOMException(kInvalidStateError,
                                    "Thrown from the native implementation.");
  return ScriptPromise();
}

ScriptPromise Internals::promiseCheckWithoutExceptionState(
    ScriptState* script_state,
    const Dictionary& arg1,
    const String& arg2,
    const Vector<String>& arg3) {
  return ScriptPromise::Cast(script_state,
                             V8String(script_state->GetIsolate(), "done"));
}

ScriptPromise Internals::promiseCheckRange(ScriptState* script_state,
                                           long arg1) {
  return ScriptPromise::Cast(script_state,
                             V8String(script_state->GetIsolate(), "done"));
}

ScriptPromise Internals::promiseCheckOverload(ScriptState* script_state,
                                              Location*) {
  return ScriptPromise::Cast(script_state,
                             V8String(script_state->GetIsolate(), "done"));
}

ScriptPromise Internals::promiseCheckOverload(ScriptState* script_state,
                                              Document*) {
  return ScriptPromise::Cast(script_state,
                             V8String(script_state->GetIsolate(), "done"));
}

ScriptPromise Internals::promiseCheckOverload(ScriptState* script_state,
                                              Location*,
                                              long,
                                              long) {
  return ScriptPromise::Cast(script_state,
                             V8String(script_state->GetIsolate(), "done"));
}

DEFINE_TRACE(Internals) {
  visitor->Trace(runtime_flags_);
  visitor->Trace(document_);
}

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

String Internals::textSurroundingNode(Node* node,
                                      int x,
                                      int y,
                                      unsigned long max_length) {
  if (!node)
    return String();

  // VisiblePosition and SurroundingText must be created with clean layout.
  node->GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
  DocumentLifecycle::DisallowTransitionScope disallow_transition(
      node->GetDocument().Lifecycle());

  if (!node->GetLayoutObject())
    return String();
  blink::WebPoint point(x, y);
  SurroundingText surrounding_text(
      CreateVisiblePosition(node->GetLayoutObject()->PositionForPoint(
                                static_cast<IntPoint>(point)))
          .DeepEquivalent()
          .ParentAnchoredEquivalent(),
      max_length);
  return surrounding_text.Content();
}

void Internals::setFocused(bool focused) {
  if (!GetFrame())
    return;

  GetFrame()->GetPage()->GetFocusController().SetFocused(focused);
}

void Internals::setInitialFocus(bool reverse) {
  if (!GetFrame())
    return;

  GetFrame()->GetDocument()->ClearFocusedElement();
  GetFrame()->GetPage()->GetFocusController().SetInitialFocus(
      reverse ? kWebFocusTypeBackward : kWebFocusTypeForward);
}

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

void Internals::setNetworkConnectionInfoOverride(
    bool on_line,
    const String& type,
    double downlink_max_mbps,
    ExceptionState& exception_state) {
  WebConnectionType webtype;
  if (type == "cellular2g") {
    webtype = kWebConnectionTypeCellular2G;
  } else if (type == "cellular3g") {
    webtype = kWebConnectionTypeCellular3G;
  } else if (type == "cellular4g") {
    webtype = kWebConnectionTypeCellular4G;
  } else if (type == "bluetooth") {
    webtype = kWebConnectionTypeBluetooth;
  } else if (type == "ethernet") {
    webtype = kWebConnectionTypeEthernet;
  } else if (type == "wifi") {
    webtype = kWebConnectionTypeWifi;
  } else if (type == "wimax") {
    webtype = kWebConnectionTypeWimax;
  } else if (type == "other") {
    webtype = kWebConnectionTypeOther;
  } else if (type == "none") {
    webtype = kWebConnectionTypeNone;
  } else if (type == "unknown") {
    webtype = kWebConnectionTypeUnknown;
  } else {
    exception_state.ThrowDOMException(
        kNotFoundError,
        ExceptionMessages::FailedToEnumerate("connection type", type));
    return;
  }
  GetNetworkStateNotifier().SetOverride(on_line, webtype, downlink_max_mbps);
}

void Internals::clearNetworkConnectionInfoOverride() {
  GetNetworkStateNotifier().ClearOverride();
}

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

bool Internals::isInCanvasFontCache(Document* document,
                                    const String& font_string) {
  return document->GetCanvasFontCache()->IsInCache(font_string);
}

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

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

void Internals::forceBlinkGCWithoutV8GC() {
  ThreadState::Current()->SetGCState(ThreadState::kFullGCScheduled);
}

String Internals::selectedHTMLForClipboard() {
  if (!GetFrame())
    return String();

  // Selection normalization and markup generation require clean layout.
  GetFrame()->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();

  return GetFrame()->Selection().SelectedHTMLForClipboard();
}

String Internals::selectedTextForClipboard() {
  if (!GetFrame() || !GetFrame()->GetDocument())
    return String();

  // Clean layout is required for extracting plain text from selection.
  GetFrame()->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();

  return GetFrame()->Selection().SelectedTextForClipboard();
}

void Internals::setVisualViewportOffset(int x, int y) {
  if (!GetFrame())
    return;

  GetFrame()->GetPage()->GetVisualViewport().SetLocation(FloatPoint(x, y));
}

int Internals::visualViewportHeight() {
  if (!GetFrame())
    return 0;

  return ExpandedIntSize(
             GetFrame()->GetPage()->GetVisualViewport().VisibleRect().Size())
      .Height();
}

int Internals::visualViewportWidth() {
  if (!GetFrame())
    return 0;

  return ExpandedIntSize(
             GetFrame()->GetPage()->GetVisualViewport().VisibleRect().Size())
      .Width();
}

float Internals::visualViewportScrollX() {
  if (!GetFrame())
    return 0;

  return GetFrame()->View()->GetScrollableArea()->GetScrollOffset().Width();
}

float Internals::visualViewportScrollY() {
  if (!GetFrame())
    return 0;

  return GetFrame()->View()->GetScrollableArea()->GetScrollOffset().Height();
}

bool Internals::isUseCounted(Document* document, uint32_t feature) {
  if (feature >= UseCounter::kNumberOfFeatures)
    return false;
  return UseCounter::IsCounted(*document,
                               static_cast<UseCounter::Feature>(feature));
}

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

bool Internals::isAnimatedCSSPropertyUseCounted(Document* document,
                                                const String& property_name) {
  return UseCounter::IsCountedAnimatedCSS(*document, property_name);
}

ScriptPromise Internals::observeUseCounter(ScriptState* script_state,
                                           Document* document,
                                           uint32_t feature) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();
  if (feature >= UseCounter::kNumberOfFeatures) {
    resolver->Reject();
    return promise;
  }

  UseCounter::Feature use_counter_feature =
      static_cast<UseCounter::Feature>(feature);
  if (UseCounter::IsCounted(*document, use_counter_feature)) {
    resolver->Resolve();
    return promise;
  }

  Page* page = document->GetPage();
  if (!page) {
    resolver->Reject();
    return promise;
  }

  page->GetUseCounter().AddObserver(
      new UseCounterObserverImpl(resolver, use_counter_feature));
  return promise;
}

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

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

ClientRectList* Internals::focusRingRects(Element* element) {
  Vector<LayoutRect> rects;
  if (element && element->GetLayoutObject())
    element->GetLayoutObject()->AddOutlineRects(
        rects, LayoutPoint(), LayoutObject::kIncludeBlockVisualOverflow);
  return ClientRectList::Create(rects);
}

ClientRectList* Internals::outlineRects(Element* element) {
  Vector<LayoutRect> rects;
  if (element && element->GetLayoutObject())
    element->GetLayoutObject()->AddOutlineRects(
        rects, LayoutPoint(), LayoutObject::kDontIncludeBlockVisualOverflow);
  return ClientRectList::Create(rects);
}

void Internals::setCapsLockState(bool enabled) {
  KeyboardEventManager::SetCurrentCapsLockState(
      enabled ? OverrideCapsLockState::kOn : OverrideCapsLockState::kOff);
}

bool Internals::setScrollbarVisibilityInScrollableArea(Node* node,
                                                       bool visible) {
  if (ScrollableArea* scrollable_area = ScrollableAreaForNode(node)) {
    scrollable_area->SetScrollbarsHidden(!visible);
    scrollable_area->GetScrollAnimator().SetScrollbarsVisibleForTesting(
        visible);
    return ScrollbarTheme::GetTheme().UsesOverlayScrollbars();
  }
  return false;
}

double Internals::monotonicTimeToZeroBasedDocumentTime(
    double platform_time,
    ExceptionState& exception_state) {
  return document_->Loader()->GetTiming().MonotonicTimeToZeroBasedDocumentTime(
      platform_time);
}

String Internals::getScrollAnimationState(Node* node) const {
  if (ScrollableArea* scrollable_area = ScrollableAreaForNode(node))
    return scrollable_area->GetScrollAnimator().RunStateAsText();
  return String();
}

String Internals::getProgrammaticScrollAnimationState(Node* node) const {
  if (ScrollableArea* scrollable_area = ScrollableAreaForNode(node))
    return scrollable_area->GetProgrammaticScrollAnimator().RunStateAsText();
  return String();
}

ClientRect* Internals::visualRect(Node* node) {
  if (!node || !node->GetLayoutObject())
    return ClientRect::Create();

  return ClientRect::Create(FloatRect(node->GetLayoutObject()->VisualRect()));
}

void Internals::crash() {
  CHECK(false) << "Intentional crash";
}

void Internals::setIsLowEndDevice(bool is_low_end_device) {
  MemoryCoordinator::SetIsLowEndDeviceForTesting(is_low_end_device);
}

}  // namespace blink
