/*
 * Copyright (C) 2009 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

// How ownership works
// -------------------
//
// Big oh represents a refcounted relationship: owner O--- ownee
//
// WebView (for the toplevel frame only)
//    O
//    |           WebFrame
//    |              O
//    |              |
//   Page O------- LocalFrame (m_mainFrame) O-------O FrameView
//                   ||
//                   ||
//               FrameLoader
//
// FrameLoader and LocalFrame are formerly one object that was split apart
// because it got too big. They basically have the same lifetime, hence the
// double line.
//
// From the perspective of the embedder, WebFrame is simply an object that it
// allocates by calling WebFrame::create() and must be freed by calling close().
// Internally, WebFrame is actually refcounted and it holds a reference to its
// corresponding LocalFrame in blink.
//
// Oilpan: the middle objects + Page in the above diagram are Oilpan heap
// allocated, WebView and FrameView are currently not. In terms of ownership
// and control, the relationships stays the same, but the references from the
// off-heap WebView to the on-heap Page is handled by a Persistent<>, not a
// RefPtr<>. Similarly, the mutual strong references between the on-heap
// LocalFrame and the off-heap FrameView is through a RefPtr (from LocalFrame
// to FrameView), and a Persistent refers to the LocalFrame in the other
// direction.
//
// From the embedder's point of view, the use of Oilpan brings no changes.
// close() must still be used to signal that the embedder is through with the
// WebFrame.  Calling it will bring about the release and finalization of the
// frame object, and everything underneath.
//
// How frames are destroyed
// ------------------------
//
// The main frame is never destroyed and is re-used. The FrameLoader is re-used
// and a reference to the main frame is kept by the Page.
//
// When frame content is replaced, all subframes are destroyed. This happens
// in Frame::detachChildren for each subframe in a pre-order depth-first
// traversal. Note that child node order may not match DOM node order!
// detachChildren() (virtually) calls Frame::detach(), which again calls
// FrameLoaderClient::detached(). This triggers WebFrame to clear its reference
// to LocalFrame. FrameLoaderClient::detached() also notifies the embedder via
// WebFrameClient that the frame is detached. Most embedders will invoke
// close() on the WebFrame at this point, triggering its deletion unless
// something else is still retaining a reference.
//
// The client is expected to be set whenever the WebLocalFrameImpl is attached
// to the DOM.

#include "web/WebLocalFrameImpl.h"

#include "bindings/core/v8/BindingSecurity.h"
#include "bindings/core/v8/DOMWrapperWorld.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "bindings/core/v8/ScriptController.h"
#include "bindings/core/v8/ScriptSourceCode.h"
#include "bindings/core/v8/ScriptValue.h"
#include "bindings/core/v8/SourceLocation.h"
#include "bindings/core/v8/V8Binding.h"
#include "bindings/core/v8/V8GCController.h"
#include "bindings/core/v8/V8PerIsolateData.h"
#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/DocumentUserGestureToken.h"
#include "core/dom/IconURL.h"
#include "core/dom/MessagePort.h"
#include "core/dom/Node.h"
#include "core/dom/NodeTraversal.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/editing/EditingUtilities.h"
#include "core/editing/Editor.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/InputMethodController.h"
#include "core/editing/PlainTextRange.h"
#include "core/editing/TextAffinity.h"
#include "core/editing/iterators/TextIterator.h"
#include "core/editing/serializers/Serialization.h"
#include "core/editing/spellcheck/SpellChecker.h"
#include "core/fetch/ResourceFetcher.h"
#include "core/fetch/SubstituteData.h"
#include "core/frame/FrameHost.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/PageScaleConstraintsSet.h"
#include "core/frame/RemoteFrame.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/frame/VisualViewport.h"
#include "core/html/HTMLAnchorElement.h"
#include "core/html/HTMLCollection.h"
#include "core/html/HTMLFormElement.h"
#include "core/html/HTMLFrameElementBase.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLHeadElement.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLLinkElement.h"
#include "core/html/PluginDocument.h"
#include "core/input/EventHandler.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutObject.h"
#include "core/layout/api/LayoutPartItem.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/loader/DocumentLoader.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/loader/FrameLoader.h"
#include "core/loader/HistoryItem.h"
#include "core/loader/MixedContentChecker.h"
#include "core/loader/NavigationScheduler.h"
#include "core/page/FocusController.h"
#include "core/page/FrameTree.h"
#include "core/page/Page.h"
#include "core/page/PrintContext.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/TransformRecorder.h"
#include "core/style/StyleInheritedData.h"
#include "core/timing/DOMWindowPerformance.h"
#include "core/timing/Performance.h"
#include "modules/app_banner/AppBannerController.h"
#include "modules/screen_orientation/ScreenOrientationController.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/UserGestureIndicator.h"
#include "platform/clipboard/ClipboardUtilities.h"
#include "platform/fonts/FontCache.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/GraphicsLayerClient.h"
#include "platform/graphics/paint/ClipRecorder.h"
#include "platform/graphics/paint/DisplayItemCacheSkipper.h"
#include "platform/graphics/paint/DrawingRecorder.h"
#include "platform/graphics/paint/SkPictureBuilder.h"
#include "platform/graphics/skia/SkiaUtils.h"
#include "platform/heap/Handle.h"
#include "platform/network/ResourceRequest.h"
#include "platform/scroll/ScrollTypes.h"
#include "platform/scroll/ScrollbarTheme.h"
#include "platform/tracing/TraceEvent.h"
#include "platform/weborigin/KURL.h"
#include "platform/weborigin/SchemeRegistry.h"
#include "platform/weborigin/SecurityPolicy.h"
#include "public/platform/InterfaceProvider.h"
#include "public/platform/InterfaceRegistry.h"
#include "public/platform/WebDoubleSize.h"
#include "public/platform/WebFloatPoint.h"
#include "public/platform/WebFloatRect.h"
#include "public/platform/WebLayer.h"
#include "public/platform/WebPoint.h"
#include "public/platform/WebRect.h"
#include "public/platform/WebSecurityOrigin.h"
#include "public/platform/WebSize.h"
#include "public/platform/WebURLError.h"
#include "public/platform/WebVector.h"
#include "public/web/WebAssociatedURLLoaderOptions.h"
#include "public/web/WebAutofillClient.h"
#include "public/web/WebConsoleMessage.h"
#include "public/web/WebDOMEvent.h"
#include "public/web/WebDocument.h"
#include "public/web/WebFindOptions.h"
#include "public/web/WebFormElement.h"
#include "public/web/WebFrameClient.h"
#include "public/web/WebFrameOwnerProperties.h"
#include "public/web/WebHistoryItem.h"
#include "public/web/WebIconURL.h"
#include "public/web/WebInputElement.h"
#include "public/web/WebInputMethodController.h"
#include "public/web/WebKit.h"
#include "public/web/WebNode.h"
#include "public/web/WebPerformance.h"
#include "public/web/WebPlugin.h"
#include "public/web/WebPrintParams.h"
#include "public/web/WebPrintPresetOptions.h"
#include "public/web/WebRange.h"
#include "public/web/WebScriptSource.h"
#include "public/web/WebSerializedScriptValue.h"
#include "public/web/WebTreeScopeType.h"
#include "skia/ext/platform_canvas.h"
#include "web/CompositionUnderlineVectorBuilder.h"
#include "web/FindInPageCoordinates.h"
#include "web/RemoteFrameOwner.h"
#include "web/SharedWorkerRepositoryClientImpl.h"
#include "web/SuspendableScriptExecutor.h"
#include "web/TextFinder.h"
#include "web/WebAssociatedURLLoaderImpl.h"
#include "web/WebDataSourceImpl.h"
#include "web/WebDevToolsAgentImpl.h"
#include "web/WebFrameWidgetImpl.h"
#include "web/WebPluginContainerImpl.h"
#include "web/WebRemoteFrameImpl.h"
#include "web/WebViewImpl.h"
#include "wtf/CurrentTime.h"
#include "wtf/HashMap.h"
#include "wtf/PtrUtil.h"
#include <algorithm>
#include <memory>
#include <utility>

namespace blink {

static int frameCount = 0;

static HeapVector<ScriptSourceCode> createSourcesVector(
    const WebScriptSource* sourcesIn,
    unsigned numSources) {
  HeapVector<ScriptSourceCode> sources;
  sources.append(sourcesIn, numSources);
  return sources;
}

WebPluginContainerImpl* WebLocalFrameImpl::pluginContainerFromFrame(
    LocalFrame* frame) {
  if (!frame)
    return 0;
  if (!frame->document() || !frame->document()->isPluginDocument())
    return 0;
  PluginDocument* pluginDocument = toPluginDocument(frame->document());
  return toWebPluginContainerImpl(pluginDocument->pluginWidget());
}

WebPluginContainerImpl* WebLocalFrameImpl::currentPluginContainer(
    LocalFrame* frame,
    Node* node) {
  WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame);
  if (pluginContainer)
    return pluginContainer;

  if (!node) {
    DCHECK(frame->document());
    node = frame->document()->focusedElement();
  }
  return toWebPluginContainerImpl(WebNode::pluginContainerFromNode(node));
}

// Simple class to override some of PrintContext behavior. Some of the methods
// made virtual so that they can be overridden by ChromePluginPrintContext.
class ChromePrintContext : public PrintContext {
  WTF_MAKE_NONCOPYABLE(ChromePrintContext);

 public:
  ChromePrintContext(LocalFrame* frame)
      : PrintContext(frame), m_printedPageWidth(0) {}

  ~ChromePrintContext() override {}

  virtual void begin(float width, float height) {
    DCHECK(!m_printedPageWidth);
    m_printedPageWidth = width;
    PrintContext::begin(m_printedPageWidth, height);
  }

  virtual float getPageShrink(int pageNumber) const {
    IntRect pageRect = m_pageRects[pageNumber];
    return m_printedPageWidth / pageRect.width();
  }

  float spoolSinglePage(WebCanvas* canvas, int pageNumber) {
    dispatchEventsForPrintingOnAllFrames();
    if (!frame()->document() || frame()->document()->layoutViewItem().isNull())
      return 0;

    frame()->view()->updateAllLifecyclePhasesExceptPaint();
    if (!frame()->document() || frame()->document()->layoutViewItem().isNull())
      return 0;

    IntRect pageRect = m_pageRects[pageNumber];
    SkPictureBuilder pictureBuilder(pageRect, &skia::GetMetaData(*canvas));
    pictureBuilder.context().setPrinting(true);

    float scale = spoolPage(pictureBuilder, pageNumber);
    pictureBuilder.endRecording()->playback(canvas);
    return scale;
  }

  void spoolAllPagesWithBoundaries(WebCanvas* canvas,
                                   const FloatSize& pageSizeInPixels) {
    dispatchEventsForPrintingOnAllFrames();
    if (!frame()->document() || frame()->document()->layoutViewItem().isNull())
      return;

    frame()->view()->updateAllLifecyclePhasesExceptPaint();
    if (!frame()->document() || frame()->document()->layoutViewItem().isNull())
      return;

    float pageHeight;
    computePageRects(FloatRect(FloatPoint(0, 0), pageSizeInPixels), 0, 0, 1,
                     pageHeight);

    const float pageWidth = pageSizeInPixels.width();
    size_t numPages = pageRects().size();
    int totalHeight = numPages * (pageSizeInPixels.height() + 1) - 1;
    IntRect allPagesRect(0, 0, pageWidth, totalHeight);

    SkPictureBuilder pictureBuilder(allPagesRect, &skia::GetMetaData(*canvas));
    pictureBuilder.context().setPrinting(true);

    {
      GraphicsContext& context = pictureBuilder.context();
      DisplayItemCacheSkipper skipper(context);

      // Fill the whole background by white.
      {
        DrawingRecorder backgroundRecorder(
            context, pictureBuilder, DisplayItem::kPrintedContentBackground,
            allPagesRect);
        context.fillRect(FloatRect(0, 0, pageWidth, totalHeight), Color::white);
      }

      int currentHeight = 0;
      for (size_t pageIndex = 0; pageIndex < numPages; pageIndex++) {
        // Draw a line for a page boundary if this isn't the first page.
        if (pageIndex > 0) {
          DrawingRecorder lineBoundaryRecorder(
              context, pictureBuilder, DisplayItem::kPrintedContentLineBoundary,
              allPagesRect);
          context.save();
          context.setStrokeColor(Color(0, 0, 255));
          context.setFillColor(Color(0, 0, 255));
          context.drawLine(IntPoint(0, currentHeight),
                           IntPoint(pageWidth, currentHeight));
          context.restore();
        }

        AffineTransform transform;
        transform.translate(0, currentHeight);
#if OS(WIN) || OS(MACOSX)
        // Account for the disabling of scaling in spoolPage. In the context
        // of spoolAllPagesWithBoundaries the scale HAS NOT been pre-applied.
        float scale = getPageShrink(pageIndex);
        transform.scale(scale, scale);
#endif
        TransformRecorder transformRecorder(context, pictureBuilder, transform);
        spoolPage(pictureBuilder, pageIndex);

        currentHeight += pageSizeInPixels.height() + 1;
      }
    }
    pictureBuilder.endRecording()->playback(canvas);
  }

 protected:
  // Spools the printed page, a subrect of frame(). Skip the scale step.
  // NativeTheme doesn't play well with scaling. Scaling is done browser side
  // instead. Returns the scale to be applied.
  // On Linux, we don't have the problem with NativeTheme, hence we let WebKit
  // do the scaling and ignore the return value.
  virtual float spoolPage(SkPictureBuilder& pictureBuilder, int pageNumber) {
    IntRect pageRect = m_pageRects[pageNumber];
    float scale = m_printedPageWidth / pageRect.width();
    GraphicsContext& context = pictureBuilder.context();

    AffineTransform transform;
#if OS(POSIX) && !OS(MACOSX)
    transform.scale(scale);
#endif
    transform.translate(static_cast<float>(-pageRect.x()),
                        static_cast<float>(-pageRect.y()));
    TransformRecorder transformRecorder(context, pictureBuilder, transform);

    ClipRecorder clipRecorder(context, pictureBuilder,
                              DisplayItem::kClipPrintedPage, pageRect);

    frame()->view()->paintContents(context, GlobalPaintNormalPhase, pageRect);

    {
      DrawingRecorder lineBoundaryRecorder(
          context, pictureBuilder,
          DisplayItem::kPrintedContentDestinationLocations, pageRect);
      outputLinkedDestinations(context, pageRect);
    }

    return scale;
  }

 private:
  void dispatchEventsForPrintingOnAllFrames() {
    HeapVector<Member<Document>> documents;
    for (Frame* currentFrame = frame(); currentFrame;
         currentFrame = currentFrame->tree().traverseNext(frame())) {
      if (currentFrame->isLocalFrame())
        documents.append(toLocalFrame(currentFrame)->document());
    }

    for (auto& doc : documents)
      doc->dispatchEventsForPrinting();
  }

  // Set when printing.
  float m_printedPageWidth;
};

// Simple class to override some of PrintContext behavior. This is used when
// the frame hosts a plugin that supports custom printing. In this case, we
// want to delegate all printing related calls to the plugin.
class ChromePluginPrintContext final : public ChromePrintContext {
 public:
  ChromePluginPrintContext(LocalFrame* frame,
                           WebPluginContainerImpl* plugin,
                           const WebPrintParams& printParams)
      : ChromePrintContext(frame),
        m_plugin(plugin),
        m_printParams(printParams) {}

  ~ChromePluginPrintContext() override {}

  DEFINE_INLINE_VIRTUAL_TRACE() {
    visitor->trace(m_plugin);
    ChromePrintContext::trace(visitor);
  }

  void begin(float width, float height) override {}

  void end() override { m_plugin->printEnd(); }

  float getPageShrink(int pageNumber) const override {
    // We don't shrink the page (maybe we should ask the widget ??)
    return 1.0;
  }

  void computePageRects(const FloatRect& printRect,
                        float headerHeight,
                        float footerHeight,
                        float userScaleFactor,
                        float& outPageHeight) override {
    m_printParams.printContentArea = IntRect(printRect);
    m_pageRects.fill(IntRect(printRect), m_plugin->printBegin(m_printParams));
  }

  void computePageRectsWithPageSize(
      const FloatSize& pageSizeInPixels) override {
    NOTREACHED();
  }

 protected:
  // Spools the printed page, a subrect of frame(). Skip the scale step.
  // NativeTheme doesn't play well with scaling. Scaling is done browser side
  // instead. Returns the scale to be applied.
  float spoolPage(SkPictureBuilder& pictureBuilder, int pageNumber) override {
    IntRect pageRect = m_pageRects[pageNumber];
    m_plugin->printPage(pageNumber, pictureBuilder.context(), pageRect);

    return 1.0;
  }

 private:
  // Set when printing.
  Member<WebPluginContainerImpl> m_plugin;
  WebPrintParams m_printParams;
};

static WebDataSource* DataSourceForDocLoader(DocumentLoader* loader) {
  return loader ? WebDataSourceImpl::fromDocumentLoader(loader) : 0;
}

// WebFrame -------------------------------------------------------------------

int WebFrame::instanceCount() {
  return frameCount;
}

WebLocalFrame* WebLocalFrame::frameForCurrentContext() {
  v8::Local<v8::Context> context =
      v8::Isolate::GetCurrent()->GetCurrentContext();
  if (context.IsEmpty())
    return 0;
  return frameForContext(context);
}

WebLocalFrame* WebLocalFrame::frameForContext(v8::Local<v8::Context> context) {
  return WebLocalFrameImpl::fromFrame(
      toLocalFrame(toFrameIfNotDetached(context)));
}

WebLocalFrame* WebLocalFrame::fromFrameOwnerElement(const WebElement& element) {
  return WebLocalFrameImpl::fromFrameOwnerElement(element);
}

bool WebLocalFrameImpl::isWebLocalFrame() const {
  return true;
}

WebLocalFrame* WebLocalFrameImpl::toWebLocalFrame() {
  return this;
}

bool WebLocalFrameImpl::isWebRemoteFrame() const {
  return false;
}

WebRemoteFrame* WebLocalFrameImpl::toWebRemoteFrame() {
  NOTREACHED();
  return 0;
}

void WebLocalFrameImpl::close() {
  m_client = nullptr;

  if (m_devToolsAgent)
    m_devToolsAgent.clear();

  m_selfKeepAlive.clear();
}

WebString WebLocalFrameImpl::uniqueName() const {
  return frame()->tree().uniqueName();
}

WebString WebLocalFrameImpl::assignedName() const {
  return frame()->tree().name();
}

void WebLocalFrameImpl::setName(const WebString& name) {
  frame()->tree().setName(name);
}

WebVector<WebIconURL> WebLocalFrameImpl::iconURLs(int iconTypesMask) const {
  // The URL to the icon may be in the header. As such, only
  // ask the loader for the icon if it's finished loading.
  if (frame()->document()->loadEventFinished())
    return frame()->document()->iconURLs(iconTypesMask);
  return WebVector<WebIconURL>();
}

void WebLocalFrameImpl::setContentSettingsClient(
    WebContentSettingsClient* contentSettingsClient) {
  m_contentSettingsClient = contentSettingsClient;
}

void WebLocalFrameImpl::setSharedWorkerRepositoryClient(
    WebSharedWorkerRepositoryClient* client) {
  m_sharedWorkerRepositoryClient =
      SharedWorkerRepositoryClientImpl::create(client);
}

ScrollableArea* WebLocalFrameImpl::layoutViewportScrollableArea() const {
  if (FrameView* view = frameView())
    return view->layoutViewportScrollableArea();
  return nullptr;
}

bool WebLocalFrameImpl::isFocused() const {
  if (!viewImpl() || !viewImpl()->page())
    return false;

  return this == WebFrame::fromFrame(
                     viewImpl()->page()->focusController().focusedFrame());
}

WebSize WebLocalFrameImpl::scrollOffset() const {
  if (ScrollableArea* scrollableArea = layoutViewportScrollableArea())
    return scrollableArea->scrollOffsetInt();
  return WebSize();
}

void WebLocalFrameImpl::setScrollOffset(const WebSize& offset) {
  if (ScrollableArea* scrollableArea = layoutViewportScrollableArea()) {
    scrollableArea->setScrollOffset(ScrollOffset(offset.width, offset.height),
                                    ProgrammaticScroll);
  }
}

WebSize WebLocalFrameImpl::contentsSize() const {
  if (FrameView* view = frameView())
    return view->contentsSize();
  return WebSize();
}

bool WebLocalFrameImpl::hasVisibleContent() const {
  LayoutPartItem layoutItem = frame()->ownerLayoutItem();
  if (!layoutItem.isNull() &&
      layoutItem.style()->visibility() != EVisibility::Visible) {
    return false;
  }

  if (FrameView* view = frameView())
    return view->visibleWidth() > 0 && view->visibleHeight() > 0;
  return false;
}

WebRect WebLocalFrameImpl::visibleContentRect() const {
  if (FrameView* view = frameView())
    return view->visibleContentRect();
  return WebRect();
}

bool WebLocalFrameImpl::hasHorizontalScrollbar() const {
  return frame() && frame()->view() && frame()->view()->horizontalScrollbar();
}

bool WebLocalFrameImpl::hasVerticalScrollbar() const {
  return frame() && frame()->view() && frame()->view()->verticalScrollbar();
}

WebView* WebLocalFrameImpl::view() const {
  return viewImpl();
}

WebDocument WebLocalFrameImpl::document() const {
  if (!frame() || !frame()->document())
    return WebDocument();
  return WebDocument(frame()->document());
}

WebPerformance WebLocalFrameImpl::performance() const {
  if (!frame())
    return WebPerformance();
  return WebPerformance(
      DOMWindowPerformance::performance(*(frame()->domWindow())));
}

void WebLocalFrameImpl::dispatchUnloadEvent() {
  if (!frame())
    return;
  SubframeLoadingDisabler disabler(frame()->document());
  frame()->loader().dispatchUnloadEvent();
}

void WebLocalFrameImpl::executeScript(const WebScriptSource& source) {
  DCHECK(frame());
  TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine),
                        OrdinalNumber::first());
  v8::HandleScope handleScope(toIsolate(frame()));
  frame()->script().executeScriptInMainWorld(
      ScriptSourceCode(source.code, source.url, position));
}

void WebLocalFrameImpl::executeScriptInIsolatedWorld(
    int worldID,
    const WebScriptSource* sourcesIn,
    unsigned numSources,
    int extensionGroup) {
  DCHECK(frame());
  CHECK_GT(worldID, 0);
  CHECK_LT(worldID, EmbedderWorldIdLimit);

  HeapVector<ScriptSourceCode> sources =
      createSourcesVector(sourcesIn, numSources);
  v8::HandleScope handleScope(toIsolate(frame()));
  frame()->script().executeScriptInIsolatedWorld(worldID, sources,
                                                 extensionGroup, 0);
}

void WebLocalFrameImpl::setIsolatedWorldSecurityOrigin(
    int worldID,
    const WebSecurityOrigin& securityOrigin) {
  DCHECK(frame());
  DOMWrapperWorld::setIsolatedWorldSecurityOrigin(worldID,
                                                  securityOrigin.get());
}

void WebLocalFrameImpl::setIsolatedWorldContentSecurityPolicy(
    int worldID,
    const WebString& policy) {
  DCHECK(frame());
  DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(worldID, policy);
}

void WebLocalFrameImpl::setIsolatedWorldHumanReadableName(
    int worldID,
    const WebString& humanReadableName) {
  DCHECK(frame());
  DOMWrapperWorld::setIsolatedWorldHumanReadableName(worldID,
                                                     humanReadableName);
}

void WebLocalFrameImpl::addMessageToConsole(const WebConsoleMessage& message) {
  DCHECK(frame());

  MessageLevel webCoreMessageLevel = LogMessageLevel;
  switch (message.level) {
    case WebConsoleMessage::LevelDebug:
      webCoreMessageLevel = DebugMessageLevel;
      break;
    case WebConsoleMessage::LevelLog:
      webCoreMessageLevel = LogMessageLevel;
      break;
    case WebConsoleMessage::LevelWarning:
      webCoreMessageLevel = WarningMessageLevel;
      break;
    case WebConsoleMessage::LevelError:
      webCoreMessageLevel = ErrorMessageLevel;
      break;
    // Unsupported values.
    case WebConsoleMessage::LevelInfo:
      break;
  }

  frame()->document()->addConsoleMessage(ConsoleMessage::create(
      OtherMessageSource, webCoreMessageLevel, message.text,
      SourceLocation::create(message.url, message.lineNumber,
                             message.columnNumber, nullptr)));
}

void WebLocalFrameImpl::collectGarbage() {
  if (!frame())
    return;
  if (!frame()->settings()->scriptEnabled())
    return;
  V8GCController::collectGarbage(v8::Isolate::GetCurrent());
}

v8::Local<v8::Value> WebLocalFrameImpl::executeScriptAndReturnValue(
    const WebScriptSource& source) {
  DCHECK(frame());

  TextPosition position(OrdinalNumber::fromOneBasedInt(source.startLine),
                        OrdinalNumber::first());
  return frame()->script().executeScriptInMainWorldAndReturnValue(
      ScriptSourceCode(source.code, source.url, position));
}

void WebLocalFrameImpl::requestExecuteScriptAndReturnValue(
    const WebScriptSource& source,
    bool userGesture,
    WebScriptExecutionCallback* callback) {
  DCHECK(frame());

  SuspendableScriptExecutor::createAndRun(
      frame(), 0, createSourcesVector(&source, 1), 0, userGesture, callback);
}

void WebLocalFrameImpl::requestExecuteV8Function(
    v8::Local<v8::Context> context,
    v8::Local<v8::Function> function,
    v8::Local<v8::Value> receiver,
    int argc,
    v8::Local<v8::Value> argv[],
    WebScriptExecutionCallback* callback) {
  DCHECK(frame());
  SuspendableScriptExecutor::createAndRun(frame(), toIsolate(frame()), context,
                                          function, receiver, argc, argv,
                                          callback);
}

void WebLocalFrameImpl::executeScriptInIsolatedWorld(
    int worldID,
    const WebScriptSource* sourcesIn,
    unsigned numSources,
    int extensionGroup,
    WebVector<v8::Local<v8::Value>>* results) {
  DCHECK(frame());
  CHECK_GT(worldID, 0);
  CHECK_LT(worldID, EmbedderWorldIdLimit);

  HeapVector<ScriptSourceCode> sources =
      createSourcesVector(sourcesIn, numSources);

  if (results) {
    Vector<v8::Local<v8::Value>> scriptResults;
    frame()->script().executeScriptInIsolatedWorld(
        worldID, sources, extensionGroup, &scriptResults);
    WebVector<v8::Local<v8::Value>> v8Results(scriptResults.size());
    for (unsigned i = 0; i < scriptResults.size(); i++)
      v8Results[i] =
          v8::Local<v8::Value>::New(toIsolate(frame()), scriptResults[i]);
    results->swap(v8Results);
  } else {
    v8::HandleScope handleScope(toIsolate(frame()));
    frame()->script().executeScriptInIsolatedWorld(worldID, sources,
                                                   extensionGroup, 0);
  }
}

void WebLocalFrameImpl::requestExecuteScriptInIsolatedWorld(
    int worldID,
    const WebScriptSource* sourcesIn,
    unsigned numSources,
    int extensionGroup,
    bool userGesture,
    WebScriptExecutionCallback* callback) {
  DCHECK(frame());
  CHECK_GT(worldID, 0);
  CHECK_LT(worldID, EmbedderWorldIdLimit);

  SuspendableScriptExecutor::createAndRun(
      frame(), worldID, createSourcesVector(sourcesIn, numSources),
      extensionGroup, userGesture, callback);
}

// TODO(bashi): Consider returning MaybeLocal.
v8::Local<v8::Value> WebLocalFrameImpl::callFunctionEvenIfScriptDisabled(
    v8::Local<v8::Function> function,
    v8::Local<v8::Value> receiver,
    int argc,
    v8::Local<v8::Value> argv[]) {
  DCHECK(frame());
  v8::Local<v8::Value> result;
  if (!V8ScriptRunner::callFunction(
           function, frame()->document(), receiver, argc,
           static_cast<v8::Local<v8::Value>*>(argv), toIsolate(frame()))
           .ToLocal(&result))
    return v8::Local<v8::Value>();
  return result;
}

v8::Local<v8::Context> WebLocalFrameImpl::mainWorldScriptContext() const {
  ScriptState* scriptState = ScriptState::forMainWorld(frame());
  DCHECK(scriptState);
  return scriptState->context();
}

bool WebFrame::scriptCanAccess(WebFrame* target) {
  return BindingSecurity::shouldAllowAccessToFrame(
      currentDOMWindow(mainThreadIsolate()), target->toImplBase()->frame(),
      BindingSecurity::ErrorReportOption::DoNotReport);
}

void WebLocalFrameImpl::reload(WebFrameLoadType loadType) {
  // TODO(clamy): Remove this function once RenderFrame calls load for all
  // requests.
  reloadWithOverrideURL(KURL(), loadType);
}

void WebLocalFrameImpl::reloadWithOverrideURL(const WebURL& overrideUrl,
                                              WebFrameLoadType loadType) {
  // TODO(clamy): Remove this function once RenderFrame calls load for all
  // requests.
  DCHECK(frame());
  DCHECK(loadType == WebFrameLoadType::Reload ||
         loadType == WebFrameLoadType::ReloadBypassingCache);
  WebURLRequest request = requestForReload(loadType, overrideUrl);
  if (request.isNull())
    return;
  load(request, loadType, WebHistoryItem(), WebHistoryDifferentDocumentLoad,
       false);
}

void WebLocalFrameImpl::reloadImage(const WebNode& webNode) {
  const Node* node = webNode.constUnwrap<Node>();
  if (isHTMLImageElement(*node)) {
    const HTMLImageElement& imageElement = toHTMLImageElement(*node);
    imageElement.forceReload();
  }
}

void WebLocalFrameImpl::reloadLoFiImages() {
  frame()->document()->fetcher()->reloadLoFiImages();
}

void WebLocalFrameImpl::loadRequest(const WebURLRequest& request) {
  // TODO(clamy): Remove this function once RenderFrame calls load for all
  // requests.
  load(request, WebFrameLoadType::Standard, WebHistoryItem(),
       WebHistoryDifferentDocumentLoad, false);
}

void WebLocalFrameImpl::loadHTMLString(const WebData& data,
                                       const WebURL& baseURL,
                                       const WebURL& unreachableURL,
                                       bool replace) {
  DCHECK(frame());
  loadData(data, WebString::fromUTF8("text/html"), WebString::fromUTF8("UTF-8"),
           baseURL, unreachableURL, replace, WebFrameLoadType::Standard,
           WebHistoryItem(), WebHistoryDifferentDocumentLoad, false);
}

void WebLocalFrameImpl::stopLoading() {
  if (!frame())
    return;
  // FIXME: Figure out what we should really do here. It seems like a bug
  // that FrameLoader::stopLoading doesn't call stopAllLoaders.
  frame()->loader().stopAllLoaders();
}

WebDataSource* WebLocalFrameImpl::provisionalDataSource() const {
  DCHECK(frame());
  return DataSourceForDocLoader(frame()->loader().provisionalDocumentLoader());
}

WebDataSource* WebLocalFrameImpl::dataSource() const {
  DCHECK(frame());
  return DataSourceForDocLoader(frame()->loader().documentLoader());
}

void WebLocalFrameImpl::enableViewSourceMode(bool enable) {
  if (frame())
    frame()->setInViewSourceMode(enable);
}

bool WebLocalFrameImpl::isViewSourceModeEnabled() const {
  if (!frame())
    return false;
  return frame()->inViewSourceMode();
}

void WebLocalFrameImpl::setReferrerForRequest(WebURLRequest& request,
                                              const WebURL& referrerURL) {
  String referrer = referrerURL.isEmpty()
                        ? frame()->document()->outgoingReferrer()
                        : String(referrerURL.string());
  request.toMutableResourceRequest().setHTTPReferrer(
      SecurityPolicy::generateReferrer(frame()->document()->getReferrerPolicy(),
                                       request.url(), referrer));
}

void WebLocalFrameImpl::dispatchWillSendRequest(WebURLRequest& request) {
  frame()->loader().client()->dispatchWillSendRequest(
      request.toMutableResourceRequest());
}

WebAssociatedURLLoader* WebLocalFrameImpl::createAssociatedURLLoader(
    const WebAssociatedURLLoaderOptions& options) {
  return new WebAssociatedURLLoaderImpl(this, options);
}

unsigned WebLocalFrameImpl::unloadListenerCount() const {
  return frame()->localDOMWindow()->pendingUnloadEventListeners();
}

void WebLocalFrameImpl::replaceSelection(const WebString& text) {
  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  bool selectReplacement =
      frame()->editor().behavior().shouldSelectReplacement();
  bool smartReplace = true;
  frame()->editor().replaceSelectionWithText(
      text, selectReplacement, smartReplace,
      InputEvent::InputType::InsertReplacementText);
}

void WebLocalFrameImpl::setMarkedText(const WebString& text,
                                      unsigned location,
                                      unsigned length) {
  Vector<CompositionUnderline> decorations;
  frame()->inputMethodController().setComposition(text, decorations, location,
                                                  length);
}

void WebLocalFrameImpl::unmarkText() {
  frame()->inputMethodController().cancelComposition();
}

bool WebLocalFrameImpl::hasMarkedText() const {
  return frame()->inputMethodController().hasComposition();
}

WebRange WebLocalFrameImpl::markedRange() const {
  return frame()->inputMethodController().compositionEphemeralRange();
}

bool WebLocalFrameImpl::firstRectForCharacterRange(
    unsigned location,
    unsigned length,
    WebRect& rectInViewport) const {
  if ((location + length < location) && (location + length))
    length = 0;

  Element* editable =
      frame()->selection().rootEditableElementOrDocumentElement();
  if (!editable)
    return false;

  // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  see http://crbug.com/590369 for more details.
  editable->document().updateStyleAndLayoutIgnorePendingStylesheets();

  const EphemeralRange range =
      PlainTextRange(location, location + length).createRange(*editable);
  if (range.isNull())
    return false;
  IntRect intRect = frame()->editor().firstRectForRange(range);
  rectInViewport = WebRect(intRect);
  rectInViewport = frame()->view()->contentsToViewport(rectInViewport);
  return true;
}

size_t WebLocalFrameImpl::characterIndexForPoint(
    const WebPoint& pointInViewport) const {
  if (!frame())
    return kNotFound;

  IntPoint point = frame()->view()->viewportToContents(pointInViewport);
  HitTestResult result = frame()->eventHandler().hitTestResultAtPoint(
      point, HitTestRequest::ReadOnly | HitTestRequest::Active);
  const EphemeralRange range =
      frame()->rangeForPoint(result.roundedPointInInnerNodeFrame());
  if (range.isNull())
    return kNotFound;
  Element* editable =
      frame()->selection().rootEditableElementOrDocumentElement();
  DCHECK(editable);
  return PlainTextRange::create(*editable, range).start();
}

bool WebLocalFrameImpl::executeCommand(const WebString& name) {
  DCHECK(frame());

  if (name.length() <= 2)
    return false;

  // Since we don't have NSControl, we will convert the format of command
  // string and call the function on Editor directly.
  String command = name;

  // Make sure the first letter is upper case.
  command.replace(0, 1, command.substring(0, 1).upper());

  // Remove the trailing ':' if existing.
  if (command[command.length() - 1] == UChar(':'))
    command = command.substring(0, command.length() - 1);

  Node* pluginLookupContextNode =
      m_contextMenuNode && name == "Copy" ? m_contextMenuNode : nullptr;
  WebPluginContainerImpl* pluginContainer =
      currentPluginContainer(frame(), pluginLookupContextNode);
  if (pluginContainer && pluginContainer->executeEditCommand(name))
    return true;

  return frame()->editor().executeCommand(command);
}

bool WebLocalFrameImpl::executeCommand(const WebString& name,
                                       const WebString& value) {
  DCHECK(frame());

  WebPluginContainerImpl* pluginContainer = currentPluginContainer(frame());
  if (pluginContainer && pluginContainer->executeEditCommand(name, value))
    return true;

  return frame()->editor().executeCommand(name, value);
}

bool WebLocalFrameImpl::isCommandEnabled(const WebString& name) const {
  DCHECK(frame());
  return frame()->editor().createCommand(name).isEnabled();
}

void WebLocalFrameImpl::enableSpellChecking(bool enable) {
  if (enable == isSpellCheckingEnabled())
    return;
  frame()->spellChecker().toggleSpellCheckingEnabled();
}

bool WebLocalFrameImpl::isSpellCheckingEnabled() const {
  return frame()->spellChecker().isSpellCheckingEnabled();
}

void WebLocalFrameImpl::replaceMisspelledRange(const WebString& text) {
  // If this caret selection has two or more markers, this function replace the
  // range covered by the first marker with the specified word as Microsoft Word
  // does.
  if (pluginContainerFromFrame(frame()))
    return;

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  see http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  frame()->spellChecker().replaceMisspelledRange(text);
}

void WebLocalFrameImpl::removeSpellingMarkers() {
  frame()->spellChecker().removeSpellingMarkers();
}

bool WebLocalFrameImpl::hasSelection() const {
  WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
  if (pluginContainer)
    return pluginContainer->plugin()->hasSelection();

  // frame()->selection()->isNone() never returns true.
  return frame()->selection().start() != frame()->selection().end();
}

WebRange WebLocalFrameImpl::selectionRange() const {
  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  return frame()->selection().selection().toNormalizedEphemeralRange();
}

WebString WebLocalFrameImpl::selectionAsText() const {
  WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
  if (pluginContainer)
    return pluginContainer->plugin()->selectionAsText();

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  String text = frame()->selection().selectedText(
      TextIteratorEmitsObjectReplacementCharacter);
#if OS(WIN)
  replaceNewlinesWithWindowsStyleNewlines(text);
#endif
  replaceNBSPWithSpace(text);
  return text;
}

WebString WebLocalFrameImpl::selectionAsMarkup() const {
  WebPluginContainerImpl* pluginContainer = pluginContainerFromFrame(frame());
  if (pluginContainer)
    return pluginContainer->plugin()->selectionAsMarkup();

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  // Selection normalization and markup generation require clean layout.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  return frame()->selection().selectedHTMLForClipboard();
}

void WebLocalFrameImpl::selectWordAroundPosition(LocalFrame* frame,
                                                 VisiblePosition position) {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::selectWordAroundPosition");

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  see http://crbug.com/590369 for more details.
  frame->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  frame->selection().selectWordAroundPosition(position);
}

bool WebLocalFrameImpl::selectWordAroundCaret() {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::selectWordAroundCaret");
  FrameSelection& selection = frame()->selection();
  if (selection.isNone() || selection.isRange())
    return false;

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  see http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  return frame()->selection().selectWordAroundPosition(
      selection.selection().visibleStart());
}

void WebLocalFrameImpl::selectRange(const WebPoint& baseInViewport,
                                    const WebPoint& extentInViewport) {
  moveRangeSelection(baseInViewport, extentInViewport);
}

void WebLocalFrameImpl::selectRange(const WebRange& webRange) {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::selectRange");

  // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  see http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  frame()->selection().setSelectedRange(
      webRange.createEphemeralRange(frame()), VP_DEFAULT_AFFINITY,
      SelectionDirectionalMode::NonDirectional, NotUserTriggered);
}

WebString WebLocalFrameImpl::rangeAsText(const WebRange& webRange) {
  // TODO(dglazkov): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  see http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  DocumentLifecycle::DisallowTransitionScope disallowTransition(
      frame()->document()->lifecycle());

  return plainText(webRange.createEphemeralRange(frame()),
                   TextIteratorEmitsObjectReplacementCharacter);
}

void WebLocalFrameImpl::moveRangeSelectionExtent(const WebPoint& point) {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::moveRangeSelectionExtent");

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  frame()->selection().moveRangeSelectionExtent(
      frame()->view()->viewportToContents(point));
}

void WebLocalFrameImpl::moveRangeSelection(
    const WebPoint& baseInViewport,
    const WebPoint& extentInViewport,
    WebFrame::TextGranularity granularity) {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::moveRangeSelection");

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  blink::TextGranularity blinkGranularity = blink::CharacterGranularity;
  if (granularity == WebFrame::WordGranularity)
    blinkGranularity = blink::WordGranularity;
  frame()->selection().moveRangeSelection(
      visiblePositionForViewportPoint(baseInViewport),
      visiblePositionForViewportPoint(extentInViewport), blinkGranularity);
}

void WebLocalFrameImpl::moveCaretSelection(const WebPoint& pointInViewport) {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::moveCaretSelection");

  // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  see http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();
  const IntPoint pointInContents =
      frame()->view()->viewportToContents(pointInViewport);
  frame()->selection().moveCaretSelection(pointInContents);
}

bool WebLocalFrameImpl::setEditableSelectionOffsets(int start, int end) {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::setEditableSelectionOffsets");

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  return frame()->inputMethodController().setEditableSelectionOffsets(
      PlainTextRange(start, end));
}

bool WebLocalFrameImpl::setCompositionFromExistingText(
    int compositionStart,
    int compositionEnd,
    const WebVector<WebCompositionUnderline>& underlines) {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::setCompositionFromExistingText");
  if (!frame()->editor().canEdit())
    return false;

  InputMethodController& inputMethodController =
      frame()->inputMethodController();
  inputMethodController.cancelComposition();

  if (compositionStart == compositionEnd)
    return true;

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  inputMethodController.setCompositionFromExistingText(
      CompositionUnderlineVectorBuilder(underlines), compositionStart,
      compositionEnd);

  return true;
}

void WebLocalFrameImpl::extendSelectionAndDelete(int before, int after) {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::extendSelectionAndDelete");
  if (WebPlugin* plugin = focusedPluginIfInputMethodSupported()) {
    plugin->extendSelectionAndDelete(before, after);
    return;
  }

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  frame()->inputMethodController().extendSelectionAndDelete(before, after);
}

void WebLocalFrameImpl::deleteSurroundingText(int before, int after) {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::deleteSurroundingText");
  if (WebPlugin* plugin = focusedPluginIfInputMethodSupported()) {
    plugin->deleteSurroundingText(before, after);
    return;
  }

  // TODO(editing-dev): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  frame()->inputMethodController().deleteSurroundingText(before, after);
}

void WebLocalFrameImpl::setCaretVisible(bool visible) {
  frame()->selection().setCaretVisible(visible);
}

VisiblePosition WebLocalFrameImpl::visiblePositionForViewportPoint(
    const WebPoint& pointInViewport) {
  return visiblePositionForContentsPoint(
      frame()->view()->viewportToContents(pointInViewport), frame());
}

WebPlugin* WebLocalFrameImpl::focusedPluginIfInputMethodSupported() {
  WebPluginContainerImpl* container =
      WebLocalFrameImpl::currentPluginContainer(frame());
  if (container && container->supportsInputMethod())
    return container->plugin();
  return 0;
}

int WebLocalFrameImpl::printBegin(const WebPrintParams& printParams,
                                  const WebNode& constrainToNode) {
  DCHECK(!frame()->document()->isFrameSet());
  WebPluginContainerImpl* pluginContainer = nullptr;
  if (constrainToNode.isNull()) {
    // If this is a plugin document, check if the plugin supports its own
    // printing. If it does, we will delegate all printing to that.
    pluginContainer = pluginContainerFromFrame(frame());
  } else {
    // We only support printing plugin nodes for now.
    pluginContainer =
        toWebPluginContainerImpl(constrainToNode.pluginContainer());
  }

  if (pluginContainer && pluginContainer->supportsPaginatedPrint())
    m_printContext =
        new ChromePluginPrintContext(frame(), pluginContainer, printParams);
  else
    m_printContext = new ChromePrintContext(frame());

  FloatRect rect(0, 0, static_cast<float>(printParams.printContentArea.width),
                 static_cast<float>(printParams.printContentArea.height));
  m_printContext->begin(rect.width(), rect.height());
  float pageHeight;
  // We ignore the overlays calculation for now since they are generated in the
  // browser. pageHeight is actually an output parameter.
  m_printContext->computePageRects(rect, 0, 0, 1.0, pageHeight);

  return static_cast<int>(m_printContext->pageCount());
}

float WebLocalFrameImpl::getPrintPageShrink(int page) {
  DCHECK(m_printContext);
  DCHECK_GE(page, 0);
  return m_printContext->getPageShrink(page);
}

float WebLocalFrameImpl::printPage(int page, WebCanvas* canvas) {
  DCHECK(m_printContext);
  DCHECK_GE(page, 0);
  DCHECK(frame());
  DCHECK(frame()->document());

  return m_printContext->spoolSinglePage(canvas, page);
}

void WebLocalFrameImpl::printEnd() {
  DCHECK(m_printContext);
  m_printContext->end();
  m_printContext.clear();
}

bool WebLocalFrameImpl::isPrintScalingDisabledForPlugin(const WebNode& node) {
  WebPluginContainerImpl* pluginContainer =
      node.isNull() ? pluginContainerFromFrame(frame())
                    : toWebPluginContainerImpl(node.pluginContainer());

  if (!pluginContainer || !pluginContainer->supportsPaginatedPrint())
    return false;

  return pluginContainer->isPrintScalingDisabled();
}

bool WebLocalFrameImpl::getPrintPresetOptionsForPlugin(
    const WebNode& node,
    WebPrintPresetOptions* presetOptions) {
  WebPluginContainerImpl* pluginContainer =
      node.isNull() ? pluginContainerFromFrame(frame())
                    : toWebPluginContainerImpl(node.pluginContainer());

  if (!pluginContainer || !pluginContainer->supportsPaginatedPrint())
    return false;

  return pluginContainer->getPrintPresetOptionsFromDocument(presetOptions);
}

bool WebLocalFrameImpl::hasCustomPageSizeStyle(int pageIndex) {
  return frame()->document()->styleForPage(pageIndex)->getPageSizeType() !=
         PAGE_SIZE_AUTO;
}

bool WebLocalFrameImpl::isPageBoxVisible(int pageIndex) {
  return frame()->document()->isPageBoxVisible(pageIndex);
}

void WebLocalFrameImpl::pageSizeAndMarginsInPixels(int pageIndex,
                                                   WebDoubleSize& pageSize,
                                                   int& marginTop,
                                                   int& marginRight,
                                                   int& marginBottom,
                                                   int& marginLeft) {
  DoubleSize size = pageSize;
  frame()->document()->pageSizeAndMarginsInPixels(
      pageIndex, size, marginTop, marginRight, marginBottom, marginLeft);
  pageSize = size;
}

WebString WebLocalFrameImpl::pageProperty(const WebString& propertyName,
                                          int pageIndex) {
  DCHECK(m_printContext);
  return m_printContext->pageProperty(frame(), propertyName.utf8().data(),
                                      pageIndex);
}

void WebLocalFrameImpl::printPagesWithBoundaries(
    WebCanvas* canvas,
    const WebSize& pageSizeInPixels) {
  DCHECK(m_printContext);

  m_printContext->spoolAllPagesWithBoundaries(
      canvas, FloatSize(pageSizeInPixels.width, pageSizeInPixels.height));
}

WebRect WebLocalFrameImpl::selectionBoundsRect() const {
  return hasSelection() ? WebRect(IntRect(frame()->selection().bounds()))
                        : WebRect();
}

WebString WebLocalFrameImpl::layerTreeAsText(bool showDebugInfo) const {
  if (!frame())
    return WebString();

  return WebString(frame()->layerTreeAsText(
      showDebugInfo ? LayerTreeIncludesDebugInfo : LayerTreeNormal));
}

// WebLocalFrameImpl public --------------------------------------------------

WebLocalFrame* WebLocalFrame::create(WebTreeScopeType scope,
                                     WebFrameClient* client,
                                     WebFrame* opener) {
  return WebLocalFrameImpl::create(scope, client, opener);
}

WebLocalFrame* WebLocalFrame::createProvisional(WebFrameClient* client,
                                                WebRemoteFrame* oldWebFrame,
                                                WebSandboxFlags flags) {
  return WebLocalFrameImpl::createProvisional(client, oldWebFrame, flags);
}

WebLocalFrameImpl* WebLocalFrameImpl::create(WebTreeScopeType scope,
                                             WebFrameClient* client,
                                             WebFrame* opener) {
  WebLocalFrameImpl* frame = new WebLocalFrameImpl(scope, client);
  frame->setOpener(opener);
  return frame;
}

WebLocalFrameImpl* WebLocalFrameImpl::createProvisional(
    WebFrameClient* client,
    WebRemoteFrame* oldWebFrame,
    WebSandboxFlags flags) {
  WebLocalFrameImpl* webFrame = new WebLocalFrameImpl(oldWebFrame, client);
  Frame* oldFrame = oldWebFrame->toImplBase()->frame();
  webFrame->setParent(oldWebFrame->parent());
  webFrame->setOpener(oldWebFrame->opener());
  // Note: this *always* temporarily sets a frame owner, even for main frames!
  // When a core Frame is created with no owner, it attempts to set itself as
  // the main frame of the Page. However, this is a provisional frame, and may
  // disappear, so Page::m_mainFrame can't be updated just yet.
  FrameOwner* tempOwner = DummyFrameOwner::create();
  // TODO(dcheng): This block is very similar to initializeCoreFrame. Try to
  // reuse it here.
  LocalFrame* frame = LocalFrame::create(
      webFrame->m_frameLoaderClientImpl.get(), oldFrame->host(), tempOwner,
      client ? client->interfaceProvider() : nullptr,
      client ? client->interfaceRegistry() : nullptr);
  // Set the name and unique name directly, bypassing any of the normal logic
  // to calculate unique name.
  frame->tree().setPrecalculatedName(
      toWebRemoteFrameImpl(oldWebFrame)->frame()->tree().name(),
      toWebRemoteFrameImpl(oldWebFrame)->frame()->tree().uniqueName());
  webFrame->setCoreFrame(frame);

  frame->setOwner(oldFrame->owner());

  if (frame->owner() && frame->owner()->isRemote())
    toRemoteFrameOwner(frame->owner())
        ->setSandboxFlags(static_cast<SandboxFlags>(flags));

  // We must call init() after m_frame is assigned because it is referenced
  // during init(). Note that this may dispatch JS events; the frame may be
  // detached after init() returns.
  frame->init();
  return webFrame;
}

WebLocalFrameImpl::WebLocalFrameImpl(WebTreeScopeType scope,
                                     WebFrameClient* client)
    : WebLocalFrame(scope),
      m_frameLoaderClientImpl(FrameLoaderClientImpl::create(this)),
      m_frameWidget(0),
      m_client(client),
      m_autofillClient(0),
      m_contentSettingsClient(0),
      m_inputEventsScaleFactorForEmulation(1),
      m_webDevToolsFrontend(0),
      m_inputMethodController(new WebInputMethodControllerImpl(this)),
      m_selfKeepAlive(this) {
  DCHECK(m_client);
  frameCount++;
}

WebLocalFrameImpl::WebLocalFrameImpl(WebRemoteFrame* oldWebFrame,
                                     WebFrameClient* client)
    : WebLocalFrameImpl(oldWebFrame->inShadowTree()
                            ? WebTreeScopeType::Shadow
                            : WebTreeScopeType::Document,
                        client) {}

WebLocalFrameImpl::~WebLocalFrameImpl() {
  // The widget for the frame, if any, must have already been closed.
  DCHECK(!m_frameWidget);
  frameCount--;
}

DEFINE_TRACE(WebLocalFrameImpl) {
  visitor->trace(m_frameLoaderClientImpl);
  visitor->trace(m_frame);
  visitor->trace(m_devToolsAgent);
  visitor->trace(m_textFinder);
  visitor->trace(m_printContext);
  visitor->trace(m_contextMenuNode);
  visitor->template registerWeakMembers<WebFrame, &WebFrame::clearWeakFrames>(
      this);
  WebFrame::traceFrames(visitor, this);
  WebFrameImplBase::trace(visitor);
}

void WebLocalFrameImpl::setCoreFrame(LocalFrame* frame) {
  m_frame = frame;
}

void WebLocalFrameImpl::initializeCoreFrame(FrameHost* host,
                                            FrameOwner* owner,
                                            const AtomicString& name,
                                            const AtomicString& uniqueName) {
  setCoreFrame(
      LocalFrame::create(m_frameLoaderClientImpl.get(), host, owner,
                         client() ? client()->interfaceProvider() : nullptr,
                         client() ? client()->interfaceRegistry() : nullptr));
  frame()->tree().setPrecalculatedName(name, uniqueName);
  // We must call init() after m_frame is assigned because it is referenced
  // during init(). Note that this may dispatch JS events; the frame may be
  // detached after init() returns.
  frame()->init();
  if (frame()) {
    if (frame()->loader().stateMachine()->isDisplayingInitialEmptyDocument() &&
        !parent() && !opener() &&
        frame()->settings()->shouldReuseGlobalForUnownedMainFrame()) {
      frame()->document()->getSecurityOrigin()->grantUniversalAccess();
    }

    // TODO(dominickn): This interface should be document-scoped rather than
    // frame-scoped, as the resulting banner event is dispatched to
    // frame()->document().
    frame()->interfaceRegistry()->addInterface(WTF::bind(
        &AppBannerController::bindMojoRequest, wrapWeakPersistent(frame())));
  }
}

LocalFrame* WebLocalFrameImpl::createChildFrame(
    const FrameLoadRequest& request,
    const AtomicString& name,
    HTMLFrameOwnerElement* ownerElement) {
  DCHECK(m_client);
  TRACE_EVENT0("blink", "WebLocalFrameImpl::createChildframe");
  WebTreeScopeType scope = frame()->document() == ownerElement->treeScope()
                               ? WebTreeScopeType::Document
                               : WebTreeScopeType::Shadow;
  WebFrameOwnerProperties ownerProperties(
      ownerElement->scrollingMode(), ownerElement->marginWidth(),
      ownerElement->marginHeight(), ownerElement->allowFullscreen(),
      ownerElement->csp(), ownerElement->delegatedPermissions());
  // FIXME: Using subResourceAttributeName as fallback is not a perfect
  // solution. subResourceAttributeName returns just one attribute name. The
  // element might not have the attribute, and there might be other attributes
  // which can identify the element.
  AtomicString uniqueName = frame()->tree().calculateUniqueNameForNewChildFrame(
      name,
      ownerElement->getAttribute(ownerElement->subResourceAttributeName()));
  WebLocalFrameImpl* webframeChild =
      toWebLocalFrameImpl(m_client->createChildFrame(
          this, scope, name, uniqueName,
          static_cast<WebSandboxFlags>(ownerElement->getSandboxFlags()),
          ownerProperties));
  if (!webframeChild)
    return nullptr;

  webframeChild->initializeCoreFrame(frame()->host(), ownerElement, name,
                                     uniqueName);
  // Initializing the core frame may cause the new child to be detached, since
  // it may dispatch a load event in the parent.
  if (!webframeChild->parent())
    return nullptr;

  // If we're moving in the back/forward list, we might want to replace the
  // content of this child frame with whatever was there at that point.
  HistoryItem* childItem = nullptr;
  if (isBackForwardLoadType(frame()->loader().loadType()) &&
      !frame()->document()->loadEventFinished())
    childItem = webframeChild->client()->historyItemForNewChildFrame();

  FrameLoadRequest newRequest = request;
  FrameLoadType loadType = FrameLoadTypeStandard;
  if (childItem) {
    newRequest = FrameLoadRequest(
        request.originDocument(),
        FrameLoader::resourceRequestFromHistoryItem(
            childItem, WebCachePolicy::UseProtocolCachePolicy));
    loadType = FrameLoadTypeInitialHistoryLoad;
  }
  webframeChild->frame()->loader().load(newRequest, loadType, childItem);

  // Note a synchronous navigation (about:blank) would have already processed
  // onload, so it is possible for the child frame to have already been
  // detached by script in the page.
  if (!webframeChild->parent())
    return nullptr;
  return webframeChild->frame();
}

void WebLocalFrameImpl::didChangeContentsSize(const IntSize& size) {
  if (m_textFinder && m_textFinder->totalMatchCount() > 0)
    m_textFinder->increaseMarkerVersion();
}

void WebLocalFrameImpl::createFrameView() {
  TRACE_EVENT0("blink", "WebLocalFrameImpl::createFrameView");

  DCHECK(
      frame());  // If frame() doesn't exist, we probably didn't init properly.

  WebViewImpl* webView = viewImpl();

  // Check if we're shutting down.
  if (!webView->page())
    return;

  bool isMainFrame = !parent();
  IntSize initialSize = (isMainFrame || !frameWidget())
                            ? webView->mainFrameSize()
                            : (IntSize)frameWidget()->size();
  bool isTransparent = !isMainFrame && parent()->isWebRemoteFrame()
                           ? true
                           : webView->isTransparent();

  frame()->createView(initialSize, webView->baseBackgroundColor(),
                      isTransparent);
  if (isMainFrame) {
    frame()->view()->setInitialViewportSize(
        webView->pageScaleConstraintsSet().initialViewportSize());
  }
  if (webView->shouldAutoResize() && frame()->isLocalRoot())
    frame()->view()->enableAutoSizeMode(webView->minAutoSize(),
                                        webView->maxAutoSize());

  frame()->view()->setInputEventsTransformForEmulation(
      m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation);
  frame()->view()->setDisplayMode(webView->displayMode());
}

WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame* frame) {
  if (!frame)
    return nullptr;
  return fromFrame(*frame);
}

WebLocalFrameImpl* WebLocalFrameImpl::fromFrame(LocalFrame& frame) {
  FrameLoaderClient* client = frame.loader().client();
  if (!client || !client->isFrameLoaderClientImpl())
    return nullptr;
  return toFrameLoaderClientImpl(client)->webFrame();
}

WebLocalFrameImpl* WebLocalFrameImpl::fromFrameOwnerElement(Element* element) {
  if (!element->isFrameOwnerElement())
    return nullptr;
  return fromFrame(
      toLocalFrame(toHTMLFrameOwnerElement(element)->contentFrame()));
}

WebViewImpl* WebLocalFrameImpl::viewImpl() const {
  if (!frame())
    return nullptr;
  return WebViewImpl::fromPage(frame()->page());
}

WebDataSourceImpl* WebLocalFrameImpl::dataSourceImpl() const {
  return static_cast<WebDataSourceImpl*>(dataSource());
}

WebDataSourceImpl* WebLocalFrameImpl::provisionalDataSourceImpl() const {
  return static_cast<WebDataSourceImpl*>(provisionalDataSource());
}

void WebLocalFrameImpl::setFindEndstateFocusAndSelection() {
  if (!m_textFinder || !m_textFinder->activeMatchFrame())
    return;

  if (Range* activeMatch = m_textFinder->activeMatch()) {
    // If the user has set the selection since the match was found, we
    // don't focus anything.
    VisibleSelection selection(frame()->selection().selection());
    if (!selection.isNone())
      return;

    // Need to clean out style and layout state before querying
    // Element::isFocusable().
    frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

    // Try to find the first focusable node up the chain, which will, for
    // example, focus links if we have found text within the link.
    Node* node = activeMatch->firstNode();
    if (node && node->isInShadowTree()) {
      if (Node* host = node->ownerShadowHost()) {
        if (isHTMLInputElement(*host) || isHTMLTextAreaElement(*host))
          node = host;
      }
    }
    const EphemeralRange activeMatchRange(activeMatch);
    if (node) {
      for (Node& runner : NodeTraversal::inclusiveAncestorsOf(*node)) {
        if (!runner.isElementNode())
          continue;
        Element& element = toElement(runner);
        if (element.isFocusable()) {
          // Found a focusable parent node. Set the active match as the
          // selection and focus to the focusable node.
          frame()->selection().setSelection(
              SelectionInDOMTree::Builder()
                  .setBaseAndExtent(activeMatchRange)
                  .build());
          frame()->document()->setFocusedElement(
              &element, FocusParams(SelectionBehaviorOnFocus::None,
                                    WebFocusTypeNone, nullptr));
          return;
        }
      }
    }

    // Iterate over all the nodes in the range until we find a focusable node.
    // This, for example, sets focus to the first link if you search for
    // text and text that is within one or more links.
    for (Node& runner : activeMatchRange.nodes()) {
      if (!runner.isElementNode())
        continue;
      Element& element = toElement(runner);
      if (element.isFocusable()) {
        frame()->document()->setFocusedElement(
            &element, FocusParams(SelectionBehaviorOnFocus::None,
                                  WebFocusTypeNone, nullptr));
        return;
      }
    }

    // No node related to the active match was focusable, so set the
    // active match as the selection (so that when you end the Find session,
    // you'll have the last thing you found highlighted) and make sure that
    // we have nothing focused (otherwise you might have text selected but
    // a link focused, which is weird).
    frame()->selection().setSelection(SelectionInDOMTree::Builder()
                                          .setBaseAndExtent(activeMatchRange)
                                          .build());
    frame()->document()->clearFocusedElement();

    // Finally clear the active match, for two reasons:
    // We just finished the find 'session' and we don't want future (potentially
    // unrelated) find 'sessions' operations to start at the same place.
    // The WebLocalFrameImpl could get reused and the activeMatch could end up
    // pointing to a document that is no longer valid. Keeping an invalid
    // reference around is just asking for trouble.
    m_textFinder->resetActiveMatch();
  }
}

void WebLocalFrameImpl::didFail(const ResourceError& error,
                                bool wasProvisional,
                                HistoryCommitType commitType) {
  if (!client())
    return;
  WebURLError webError = error;
  WebHistoryCommitType webCommitType =
      static_cast<WebHistoryCommitType>(commitType);

  if (WebPluginContainerImpl* plugin = pluginContainerFromFrame(frame()))
    plugin->didFailLoading(error);

  if (wasProvisional)
    client()->didFailProvisionalLoad(this, webError, webCommitType);
  else
    client()->didFailLoad(this, webError, webCommitType);
}

void WebLocalFrameImpl::didFinish() {
  if (!client())
    return;

  if (WebPluginContainerImpl* plugin = pluginContainerFromFrame(frame()))
    plugin->didFinishLoading();

  client()->didFinishLoad(this);
}

void WebLocalFrameImpl::setCanHaveScrollbars(bool canHaveScrollbars) {
  frame()->view()->setCanHaveScrollbars(canHaveScrollbars);
}

void WebLocalFrameImpl::setInputEventsTransformForEmulation(
    const IntSize& offset,
    float contentScaleFactor) {
  m_inputEventsOffsetForEmulation = offset;
  m_inputEventsScaleFactorForEmulation = contentScaleFactor;
  if (frame()->view())
    frame()->view()->setInputEventsTransformForEmulation(
        m_inputEventsOffsetForEmulation, m_inputEventsScaleFactorForEmulation);
}

void WebLocalFrameImpl::loadJavaScriptURL(const KURL& url) {
  // This is copied from ScriptController::executeScriptIfJavaScriptURL.
  // Unfortunately, we cannot just use that method since it is private, and
  // it also doesn't quite behave as we require it to for bookmarklets. The
  // key difference is that we need to suppress loading the string result
  // from evaluating the JS URL if executing the JS URL resulted in a
  // location change. We also allow a JS URL to be loaded even if scripts on
  // the page are otherwise disabled.

  if (!frame()->document() || !frame()->page())
    return;

  Document* ownerDocument(frame()->document());

  // Protect privileged pages against bookmarklets and other javascript
  // manipulations.
  if (SchemeRegistry::shouldTreatURLSchemeAsNotAllowingJavascriptURLs(
          frame()->document()->url().protocol()))
    return;

  String script = decodeURLEscapeSequences(
      url.getString().substring(strlen("javascript:")));
  UserGestureIndicator gestureIndicator(DocumentUserGestureToken::create(
      frame()->document(), UserGestureToken::NewGesture));
  v8::HandleScope handleScope(toIsolate(frame()));
  v8::Local<v8::Value> result =
      frame()->script().executeScriptInMainWorldAndReturnValue(
          ScriptSourceCode(script));
  if (result.IsEmpty() || !result->IsString())
    return;
  String scriptResult = toCoreString(v8::Local<v8::String>::Cast(result));
  if (!frame()->navigationScheduler().locationChangePending())
    frame()->loader().replaceDocumentWhileExecutingJavaScriptURL(scriptResult,
                                                                 ownerDocument);
}

HitTestResult WebLocalFrameImpl::hitTestResultForVisualViewportPos(
    const IntPoint& posInViewport) {
  IntPoint rootFramePoint(
      frame()->host()->visualViewport().viewportToRootFrame(posInViewport));
  IntPoint docPoint(frame()->view()->rootFrameToContents(rootFramePoint));
  HitTestResult result = frame()->eventHandler().hitTestResultAtPoint(
      docPoint, HitTestRequest::ReadOnly | HitTestRequest::Active);
  result.setToShadowHostIfInUserAgentShadowRoot();
  return result;
}

static void ensureFrameLoaderHasCommitted(FrameLoader& frameLoader) {
  // Internally, Blink uses CommittedMultipleRealLoads to track whether the
  // next commit should create a new history item or not. Ensure we have
  // reached that state.
  if (frameLoader.stateMachine()->committedMultipleRealLoads())
    return;
  frameLoader.stateMachine()->advanceTo(
      FrameLoaderStateMachine::CommittedMultipleRealLoads);
}

void WebLocalFrameImpl::setAutofillClient(WebAutofillClient* autofillClient) {
  m_autofillClient = autofillClient;
}

WebAutofillClient* WebLocalFrameImpl::autofillClient() {
  return m_autofillClient;
}

void WebLocalFrameImpl::setDevToolsAgentClient(
    WebDevToolsAgentClient* devToolsClient) {
  DCHECK(devToolsClient);
  m_devToolsAgent = WebDevToolsAgentImpl::create(this, devToolsClient);
}

WebDevToolsAgent* WebLocalFrameImpl::devToolsAgent() {
  return m_devToolsAgent.get();
}

WebLocalFrameImpl* WebLocalFrameImpl::localRoot() {
  // This can't use the LocalFrame::localFrameRoot, since it may be called
  // when the WebLocalFrame exists but the core LocalFrame does not.
  // TODO(alexmos, dcheng): Clean this up to only calculate this in one place.
  WebLocalFrameImpl* localRoot = this;
  while (localRoot->parent() && localRoot->parent()->isWebLocalFrame())
    localRoot = toWebLocalFrameImpl(localRoot->parent());
  return localRoot;
}

void WebLocalFrameImpl::sendPings(const WebURL& destinationURL) {
  DCHECK(frame());
  DCHECK(m_contextMenuNode.get());
  Element* anchor = m_contextMenuNode->enclosingLinkEventParentOrSelf();
  if (isHTMLAnchorElement(anchor))
    toHTMLAnchorElement(anchor)->sendPings(destinationURL);
}

bool WebLocalFrameImpl::dispatchBeforeUnloadEvent(bool isReload) {
  if (!frame())
    return true;

  return frame()->loader().shouldClose(isReload);
}

WebURLRequest WebLocalFrameImpl::requestFromHistoryItem(
    const WebHistoryItem& item,
    WebCachePolicy cachePolicy) const {
  HistoryItem* historyItem = item;
  ResourceRequest request =
      FrameLoader::resourceRequestFromHistoryItem(historyItem, cachePolicy);
  return WrappedResourceRequest(request);
}

WebURLRequest WebLocalFrameImpl::requestForReload(
    WebFrameLoadType loadType,
    const WebURL& overrideUrl) const {
  DCHECK(frame());
  ResourceRequest request = frame()->loader().resourceRequestForReload(
      static_cast<FrameLoadType>(loadType), overrideUrl);
  return WrappedResourceRequest(request);
}

void WebLocalFrameImpl::load(const WebURLRequest& request,
                             WebFrameLoadType webFrameLoadType,
                             const WebHistoryItem& item,
                             WebHistoryLoadType webHistoryLoadType,
                             bool isClientRedirect) {
  DCHECK(frame());
  DCHECK(!request.isNull());
  const ResourceRequest& resourceRequest = request.toResourceRequest();

  if (resourceRequest.url().protocolIs("javascript") &&
      webFrameLoadType == WebFrameLoadType::Standard) {
    loadJavaScriptURL(resourceRequest.url());
    return;
  }

  FrameLoadRequest frameRequest = FrameLoadRequest(nullptr, resourceRequest);
  if (isClientRedirect)
    frameRequest.setClientRedirect(ClientRedirectPolicy::ClientRedirect);
  HistoryItem* historyItem = item;
  frame()->loader().load(
      frameRequest, static_cast<FrameLoadType>(webFrameLoadType), historyItem,
      static_cast<HistoryLoadType>(webHistoryLoadType));
}

void WebLocalFrameImpl::loadData(const WebData& data,
                                 const WebString& mimeType,
                                 const WebString& textEncoding,
                                 const WebURL& baseURL,
                                 const WebURL& unreachableURL,
                                 bool replace,
                                 WebFrameLoadType webFrameLoadType,
                                 const WebHistoryItem& item,
                                 WebHistoryLoadType webHistoryLoadType,
                                 bool isClientRedirect) {
  DCHECK(frame());

  // If we are loading substitute data to replace an existing load, then
  // inherit all of the properties of that original request. This way,
  // reload will re-attempt the original request. It is essential that
  // we only do this when there is an unreachableURL since a non-empty
  // unreachableURL informs FrameLoader::reload to load unreachableURL
  // instead of the currently loaded URL.
  ResourceRequest request;
  if (replace && !unreachableURL.isEmpty() &&
      frame()->loader().provisionalDocumentLoader())
    request = frame()->loader().provisionalDocumentLoader()->originalRequest();
  request.setURL(baseURL);
  request.setCheckForBrowserSideNavigation(false);

  FrameLoadRequest frameRequest(
      0, request, SubstituteData(data, mimeType, textEncoding, unreachableURL));
  DCHECK(frameRequest.substituteData().isValid());
  frameRequest.setReplacesCurrentItem(replace);
  if (isClientRedirect)
    frameRequest.setClientRedirect(ClientRedirectPolicy::ClientRedirect);

  HistoryItem* historyItem = item;
  frame()->loader().load(
      frameRequest, static_cast<FrameLoadType>(webFrameLoadType), historyItem,
      static_cast<HistoryLoadType>(webHistoryLoadType));
}

bool WebLocalFrameImpl::maybeRenderFallbackContent(
    const WebURLError& error) const {
  DCHECK(frame());

  if (!frame()->owner() || !frame()->owner()->canRenderFallbackContent())
    return false;

  FrameLoader& frameloader = frame()->loader();
  frameloader.loadFailed(frameloader.documentLoader(), error);
  return true;
}

bool WebLocalFrameImpl::isLoading() const {
  if (!frame() || !frame()->document())
    return false;
  return frame()->loader().stateMachine()->isDisplayingInitialEmptyDocument() ||
         frame()->loader().provisionalDocumentLoader() ||
         !frame()->document()->loadEventFinished();
}

bool WebLocalFrameImpl::isNavigationScheduledWithin(
    double intervalInSeconds) const {
  return frame() &&
         frame()->navigationScheduler().isNavigationScheduledWithin(
             intervalInSeconds);
}

void WebLocalFrameImpl::setCommittedFirstRealLoad() {
  DCHECK(frame());
  ensureFrameLoaderHasCommitted(frame()->loader());
}

void WebLocalFrameImpl::setHasReceivedUserGesture() {
  if (frame())
    frame()->document()->setHasReceivedUserGesture();
}

void WebLocalFrameImpl::sendOrientationChangeEvent() {
  if (!frame())
    return;

  // Screen Orientation API
  if (ScreenOrientationController::from(*frame()))
    ScreenOrientationController::from(*frame())->notifyOrientationChanged();

  // Legacy window.orientation API
  if (RuntimeEnabledFeatures::orientationEventEnabled() && frame()->domWindow())
    frame()->localDOMWindow()->sendOrientationChangeEvent();
}

void WebLocalFrameImpl::didCallAddSearchProvider() {
  UseCounter::count(frame(), UseCounter::ExternalAddSearchProvider);
}

void WebLocalFrameImpl::didCallIsSearchProviderInstalled() {
  UseCounter::count(frame(), UseCounter::ExternalIsSearchProviderInstalled);
}

void WebLocalFrameImpl::requestFind(int identifier,
                                    const WebString& searchText,
                                    const WebFindOptions& options) {
  // Send "no results" if this frame has no visible content.
  if (!hasVisibleContent() && !options.force) {
    client()->reportFindInPageMatchCount(identifier, 0 /* count */,
                                         true /* finalUpdate */);
    return;
  }

  WebRange currentSelection = selectionRange();
  bool result = false;
  bool activeNow = false;

  // Search for an active match only if this frame is focused or if this is a
  // find next request.
  if (isFocused() || options.findNext) {
    result = find(identifier, searchText, options, false /* wrapWithinFrame */,
                  &activeNow);
  }

  if (result && !options.findNext) {
    // Indicate that at least one match has been found. 1 here means
    // possibly more matches could be coming.
    client()->reportFindInPageMatchCount(identifier, 1 /* count */,
                                         false /* finalUpdate */);
  }

  // There are three cases in which scoping is needed:
  //
  // (1) This is an initial find request (|options.findNext| is false). This
  // will be the first scoping effort for this find session.
  //
  // (2) Something has been selected since the last search. This means that we
  // cannot just increment the current match ordinal; we need to re-generate
  // it.
  //
  // (3) TextFinder::Find() found what should be the next match (|result| is
  // true), but was unable to activate it (|activeNow| is false). This means
  // that the text containing this match was dynamically added since the last
  // scope of the frame. The frame needs to be re-scoped so that any matches
  // in the new text can be highlighted and included in the reported number of
  // matches.
  //
  // If none of these cases are true, then we just report the current match
  // count without scoping.
  if (/* (1) */ options.findNext && /* (2) */ currentSelection.isNull() &&
      /* (3) */ !(result && !activeNow)) {
    // Force report of the actual count.
    increaseMatchCount(0, identifier);
    return;
  }

  // Scoping effort begins.
  ensureTextFinder().resetMatchCount();
  textFinder()->cancelPendingScopingEffort();

  // Start a new scoping request. If the scoping function determines that it
  // needs to scope, it will defer until later.
  textFinder()->scopeStringMatches(identifier, searchText, options,
                                   true /* reset */);
}

bool WebLocalFrameImpl::find(int identifier,
                             const WebString& searchText,
                             const WebFindOptions& options,
                             bool wrapWithinFrame,
                             bool* activeNow) {
  if (!frame())
    return false;

  // Unlikely, but just in case we try to find-in-page on a detached frame.
  DCHECK(frame()->host());

  // Up-to-date, clean tree is required for finding text in page, since it
  // relies on TextIterator to look over the text.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  return ensureTextFinder().find(identifier, searchText, options,
                                 wrapWithinFrame, activeNow);
}

void WebLocalFrameImpl::stopFinding(StopFindAction action) {
  bool clearSelection = action == StopFindActionClearSelection;
  if (clearSelection)
    executeCommand(WebString::fromUTF8("Unselect"));

  if (m_textFinder) {
    if (!clearSelection)
      setFindEndstateFocusAndSelection();
    m_textFinder->stopFindingAndClearSelection();
  }

  if (action == StopFindActionActivateSelection && isFocused()) {
    WebDocument doc = document();
    if (!doc.isNull()) {
      WebElement element = doc.focusedElement();
      if (!element.isNull())
        element.simulateClick();
    }
  }
}

void WebLocalFrameImpl::increaseMatchCount(int count, int identifier) {
  ensureTextFinder().increaseMatchCount(identifier, count);
}

void WebLocalFrameImpl::dispatchMessageEventWithOriginCheck(
    const WebSecurityOrigin& intendedTargetOrigin,
    const WebDOMEvent& event) {
  DCHECK(!event.isNull());
  frame()->localDOMWindow()->dispatchMessageEventWithOriginCheck(
      intendedTargetOrigin.get(), event,
      SourceLocation::create(String(), 0, 0, nullptr));
}

int WebLocalFrameImpl::findMatchMarkersVersion() const {
  if (m_textFinder)
    return m_textFinder->findMatchMarkersVersion();
  return 0;
}

int WebLocalFrameImpl::selectNearestFindMatch(const WebFloatPoint& point,
                                              WebRect* selectionRect) {
  return ensureTextFinder().selectNearestFindMatch(point, selectionRect);
}

float WebLocalFrameImpl::distanceToNearestFindMatch(
    const WebFloatPoint& point) {
  float nearestDistance;
  ensureTextFinder().nearestFindMatch(point, &nearestDistance);
  return nearestDistance;
}

WebFloatRect WebLocalFrameImpl::activeFindMatchRect() {
  if (m_textFinder)
    return m_textFinder->activeFindMatchRect();
  return WebFloatRect();
}

void WebLocalFrameImpl::findMatchRects(WebVector<WebFloatRect>& outputRects) {
  ensureTextFinder().findMatchRects(outputRects);
}

void WebLocalFrameImpl::setTickmarks(const WebVector<WebRect>& tickmarks) {
  if (frameView()) {
    Vector<IntRect> tickmarksConverted(tickmarks.size());
    for (size_t i = 0; i < tickmarks.size(); ++i)
      tickmarksConverted[i] = tickmarks[i];
    frameView()->setTickmarks(tickmarksConverted);
  }
}

void WebLocalFrameImpl::willBeDetached() {
  if (m_devToolsAgent)
    m_devToolsAgent->willBeDestroyed();
}

void WebLocalFrameImpl::willDetachParent() {
  // Do not expect string scoping results from any frames that got detached
  // in the middle of the operation.
  if (m_textFinder && m_textFinder->scopingInProgress()) {
    // There is a possibility that the frame being detached was the only
    // pending one. We need to make sure final replies can be sent.
    m_textFinder->flushCurrentScoping();

    m_textFinder->cancelPendingScopingEffort();
  }
}

TextFinder* WebLocalFrameImpl::textFinder() const {
  return m_textFinder;
}

TextFinder& WebLocalFrameImpl::ensureTextFinder() {
  if (!m_textFinder)
    m_textFinder = TextFinder::create(*this);

  return *m_textFinder;
}

void WebLocalFrameImpl::setFrameWidget(WebFrameWidgetBase* frameWidget) {
  m_frameWidget = frameWidget;
}

WebFrameWidgetBase* WebLocalFrameImpl::frameWidget() const {
  return m_frameWidget;
}

void WebLocalFrameImpl::copyImageAt(const WebPoint& posInViewport) {
  HitTestResult result = hitTestResultForVisualViewportPos(posInViewport);
  if (!isHTMLCanvasElement(result.innerNodeOrImageMapImage()) &&
      result.absoluteImageURL().isEmpty()) {
    // There isn't actually an image at these coordinates.  Might be because
    // the window scrolled while the context menu was open or because the page
    // changed itself between when we thought there was an image here and when
    // we actually tried to retreive the image.
    //
    // FIXME: implement a cache of the most recent HitTestResult to avoid having
    //        to do two hit tests.
    return;
  }

  // TODO(xiaochengh): The use of updateStyleAndLayoutIgnorePendingStylesheets
  // needs to be audited.  See http://crbug.com/590369 for more details.
  frame()->document()->updateStyleAndLayoutIgnorePendingStylesheets();

  frame()->editor().copyImage(result);
}

void WebLocalFrameImpl::saveImageAt(const WebPoint& posInViewport) {
  Node* node = hitTestResultForVisualViewportPos(posInViewport)
                   .innerNodeOrImageMapImage();
  if (!node || !(isHTMLCanvasElement(*node) || isHTMLImageElement(*node)))
    return;

  String url = toElement(*node).imageSourceURL();
  if (!KURL(KURL(), url).protocolIsData())
    return;

  m_client->saveImageFromDataURL(url);
}

WebSandboxFlags WebLocalFrameImpl::effectiveSandboxFlags() const {
  if (!frame())
    return WebSandboxFlags::None;
  return static_cast<WebSandboxFlags>(
      frame()->loader().effectiveSandboxFlags());
}

void WebLocalFrameImpl::forceSandboxFlags(WebSandboxFlags flags) {
  frame()->loader().forceSandboxFlags(static_cast<SandboxFlags>(flags));
}

void WebLocalFrameImpl::clearActiveFindMatch() {
  ensureTextFinder().clearActiveFindMatch();
}

void WebLocalFrameImpl::usageCountChromeLoadTimes(const WebString& metric) {
  UseCounter::Feature feature = UseCounter::ChromeLoadTimesUnknown;
  if (metric == "requestTime") {
    feature = UseCounter::ChromeLoadTimesRequestTime;
  } else if (metric == "startLoadTime") {
    feature = UseCounter::ChromeLoadTimesStartLoadTime;
  } else if (metric == "commitLoadTime") {
    feature = UseCounter::ChromeLoadTimesCommitLoadTime;
  } else if (metric == "finishDocumentLoadTime") {
    feature = UseCounter::ChromeLoadTimesFinishDocumentLoadTime;
  } else if (metric == "finishLoadTime") {
    feature = UseCounter::ChromeLoadTimesFinishLoadTime;
  } else if (metric == "firstPaintTime") {
    feature = UseCounter::ChromeLoadTimesFirstPaintTime;
  } else if (metric == "firstPaintAfterLoadTime") {
    feature = UseCounter::ChromeLoadTimesFirstPaintAfterLoadTime;
  } else if (metric == "navigationType") {
    feature = UseCounter::ChromeLoadTimesNavigationType;
  } else if (metric == "wasFetchedViaSpdy") {
    feature = UseCounter::ChromeLoadTimesWasFetchedViaSpdy;
  } else if (metric == "wasNpnNegotiated") {
    feature = UseCounter::ChromeLoadTimesWasNpnNegotiated;
  } else if (metric == "npnNegotiatedProtocol") {
    feature = UseCounter::ChromeLoadTimesNpnNegotiatedProtocol;
  } else if (metric == "wasAlternateProtocolAvailable") {
    feature = UseCounter::ChromeLoadTimesWasAlternateProtocolAvailable;
  } else if (metric == "connectionInfo") {
    feature = UseCounter::ChromeLoadTimesConnectionInfo;
  }
  UseCounter::count(frame(), feature);
}

WebInputMethodControllerImpl* WebLocalFrameImpl::inputMethodController() const {
  return m_inputMethodController.get();
}

}  // namespace blink
