Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / frame / LocalFrame.cpp
index 9c32d1e..9b5c504 100644 (file)
@@ -48,6 +48,7 @@
 #include "core/frame/LocalDOMWindow.h"
 #include "core/frame/Settings.h"
 #include "core/html/HTMLFrameElementBase.h"
+#include "core/html/HTMLPlugInElement.h"
 #include "core/inspector/ConsoleMessageStorage.h"
 #include "core/inspector/InspectorInstrumentation.h"
 #include "core/loader/FrameLoaderClient.h"
@@ -73,7 +74,33 @@ namespace blink {
 
 using namespace HTMLNames;
 
-static inline float parentPageZoomFactor(LocalFrame* frame)
+namespace {
+
+struct ScopedFramePaintingState {
+    ScopedFramePaintingState(LocalFrame* frame, Node* node)
+        : frame(frame)
+        , node(node)
+        , paintBehavior(frame->view()->paintBehavior())
+    {
+        ASSERT(!node || node->renderer());
+        if (node)
+            node->renderer()->updateDragState(true);
+    }
+
+    ~ScopedFramePaintingState()
+    {
+        if (node && node->renderer())
+            node->renderer()->updateDragState(false);
+        frame->view()->setPaintBehavior(paintBehavior);
+        frame->view()->setNodeToDraw(0);
+    }
+
+    LocalFrame* frame;
+    Node* node;
+    PaintBehavior paintBehavior;
+};
+
+inline float parentPageZoomFactor(LocalFrame* frame)
 {
     Frame* parent = frame->tree().parent();
     if (!parent || !parent->isLocalFrame())
@@ -81,7 +108,7 @@ static inline float parentPageZoomFactor(LocalFrame* frame)
     return toLocalFrame(parent)->pageZoomFactor();
 }
 
-static inline float parentTextZoomFactor(LocalFrame* frame)
+inline float parentTextZoomFactor(LocalFrame* frame)
 {
     Frame* parent = frame->tree().parent();
     if (!parent || !parent->isLocalFrame())
@@ -89,22 +116,7 @@ static inline float parentTextZoomFactor(LocalFrame* frame)
     return toLocalFrame(parent)->textZoomFactor();
 }
 
-inline LocalFrame::LocalFrame(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
-    : Frame(client, host, owner)
-    , m_loader(this)
-    , m_navigationScheduler(this)
-    , m_script(adoptPtr(new ScriptController(this)))
-    , m_editor(Editor::create(*this))
-    , m_spellChecker(SpellChecker::create(*this))
-    , m_selection(FrameSelection::create(this))
-    , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this)))
-    , m_console(FrameConsole::create(*this))
-    , m_inputMethodController(InputMethodController::create(*this))
-    , m_pageZoomFactor(parentPageZoomFactor(this))
-    , m_textZoomFactor(parentTextZoomFactor(this))
-    , m_inViewSourceMode(false)
-{
-}
+} // namespace
 
 PassRefPtrWillBeRawPtr<LocalFrame> LocalFrame::create(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
 {
@@ -113,6 +125,75 @@ PassRefPtrWillBeRawPtr<LocalFrame> LocalFrame::create(FrameLoaderClient* client,
     return frame.release();
 }
 
+void LocalFrame::setView(PassRefPtrWillBeRawPtr<FrameView> view)
+{
+    ASSERT(!m_view || m_view != view);
+    detachView();
+
+    // Prepare for destruction now, so any unload event handlers get run and the LocalDOMWindow is
+    // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
+    // these calls to work.
+    if (!view && document() && document()->isActive()) {
+        // FIXME: We don't call willRemove here. Why is that OK?
+        document()->prepareForDestruction();
+    }
+
+    eventHandler().clear();
+
+    m_view = view;
+
+    if (m_view && isMainFrame() && !settings()->pinchVirtualViewportEnabled())
+        m_view->setVisibleContentScaleFactor(page()->pageScaleFactor());
+}
+
+void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
+    ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
+    ScrollbarMode verticalScrollbarMode, bool verticalLock)
+{
+    ASSERT(this);
+    ASSERT(page());
+
+    bool isLocalRoot = this->isLocalRoot();
+
+    if (isLocalRoot && view())
+        view()->setParentVisible(false);
+
+    setView(nullptr);
+
+    RefPtrWillBeRawPtr<FrameView> frameView = nullptr;
+    if (isLocalRoot) {
+        frameView = FrameView::create(this, viewportSize);
+
+        // The layout size is set by WebViewImpl to support @viewport
+        frameView->setLayoutSizeFixedToFrameSize(false);
+    } else {
+        frameView = FrameView::create(this);
+    }
+
+    frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
+
+    setView(frameView);
+
+    frameView->updateBackgroundRecursively(backgroundColor, transparent);
+
+    if (isLocalRoot)
+        frameView->setParentVisible(true);
+
+    // FIXME: Not clear what the right thing for OOPI is here.
+    if (ownerRenderer()) {
+        HTMLFrameOwnerElement* owner = deprecatedLocalOwner();
+        ASSERT(owner);
+        // FIXME: OOPI might lead to us temporarily lying to a frame and telling it
+        // that it's owned by a FrameOwner that knows nothing about it. If we're
+        // lying to this frame, don't let it clobber the existing widget.
+        if (owner->contentFrame() == this)
+            owner->setWidget(frameView);
+    }
+
+    if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner())
+        view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
+}
+
 LocalFrame::~LocalFrame()
 {
 #if ENABLE(OILPAN)
@@ -133,9 +214,8 @@ LocalFrame::~LocalFrame()
     m_loader.clear();
     setDOMWindow(nullptr);
 
-    HashSet<RawPtr<FrameDestructionObserver> >::iterator stop = m_destructionObservers.end();
-    for (HashSet<RawPtr<FrameDestructionObserver> >::iterator it = m_destructionObservers.begin(); it != stop; ++it)
-        (*it)->frameDestroyed();
+    for (const auto& frameDestructionObserver : m_destructionObservers)
+        frameDestructionObserver->frameDestroyed();
 #endif
 }
 
@@ -145,18 +225,32 @@ void LocalFrame::trace(Visitor* visitor)
     visitor->trace(m_destructionObservers);
     visitor->trace(m_loader);
     visitor->trace(m_navigationScheduler);
+    visitor->trace(m_view);
+    visitor->trace(m_domWindow);
     visitor->trace(m_pagePopupOwner);
+    visitor->trace(m_script);
     visitor->trace(m_editor);
     visitor->trace(m_spellChecker);
     visitor->trace(m_selection);
     visitor->trace(m_eventHandler);
     visitor->trace(m_console);
     visitor->trace(m_inputMethodController);
+    visitor->registerWeakMembers<LocalFrame, &LocalFrame::clearWeakMembers>(this);
     HeapSupplementable<LocalFrame>::trace(visitor);
 #endif
     Frame::trace(visitor);
 }
 
+LocalDOMWindow* LocalFrame::domWindow() const
+{
+    return m_domWindow.get();
+}
+
+void LocalFrame::navigate(Document& originDocument, const KURL& url, bool lockBackForwardList)
+{
+    m_navigationScheduler.scheduleLocationChange(&originDocument, url.string(), lockBackForwardList);
+}
+
 void LocalFrame::detach()
 {
     // A lot of the following steps can result in the current frame being
@@ -169,137 +263,38 @@ void LocalFrame::detach()
     // will trigger the unload event handlers of any child frames, and those event
     // handlers might start a new subresource load in this frame.
     m_loader.stopAllLoaders();
-    m_loader.detachFromParent();
-}
-
-bool LocalFrame::inScope(TreeScope* scope) const
-{
-    ASSERT(scope);
-    Document* doc = document();
-    if (!doc)
-        return false;
-    // FIXME: This check is broken in for OOPI.
-    HTMLFrameOwnerElement* owner = doc->ownerElement();
-    if (!owner)
-        return false;
-    return owner->treeScope() == scope;
-}
-
-void LocalFrame::detachView()
-{
-    // We detach the FrameView's custom scroll bars as early as
-    // possible to prevent m_doc->detach() from messing with the view
-    // such that its scroll bars won't be torn down.
-    //
-    // FIXME: We should revisit this.
-    if (m_view)
-        m_view->prepareForDetach();
-}
-
-void LocalFrame::setView(PassRefPtr<FrameView> view)
-{
-    detachView();
-
-    // Prepare for destruction now, so any unload event handlers get run and the LocalDOMWindow is
-    // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
-    // these calls to work.
-    if (!view && document() && document()->isActive()) {
-        // FIXME: We don't call willRemove here. Why is that OK?
-        document()->prepareForDestruction();
-    }
-
-    eventHandler().clear();
-
-    m_view = view;
-
-    if (m_view && isMainFrame()) {
-        if (settings()->pinchVirtualViewportEnabled())
-            m_host->pinchViewport().mainFrameDidChangeSize();
-        else
-            m_view->setVisibleContentScaleFactor(page()->pageScaleFactor());
-    }
-}
-
-void LocalFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio)
-{
-    // In setting printing, we should not validate resources already cached for the document.
-    // See https://bugs.webkit.org/show_bug.cgi?id=43704
-    ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher());
-
-    document()->setPrinting(printing);
-    view()->adjustMediaTypeForPrinting(printing);
-
-    document()->styleResolverChanged();
-    if (shouldUsePrintingLayout()) {
-        view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio);
-    } else {
-        view()->forceLayout();
-        view()->adjustViewSize();
-    }
-
-    // Subframes of the one we're printing don't lay out to the page size.
-    for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
-        if (child->isLocalFrame())
-            toLocalFrame(child.get())->setPrinting(printing, FloatSize(), FloatSize(), 0);
-    }
-}
-
-bool LocalFrame::shouldUsePrintingLayout() const
-{
-    // Only top frame being printed should be fit to page size.
-    // Subframes should be constrained by parents only.
-    return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing());
-}
-
-FloatSize LocalFrame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
-{
-    FloatSize resultSize;
-    if (!contentRenderer())
-        return FloatSize();
-
-    if (contentRenderer()->style()->isHorizontalWritingMode()) {
-        ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
-        float ratio = originalSize.height() / originalSize.width();
-        resultSize.setWidth(floorf(expectedSize.width()));
-        resultSize.setHeight(floorf(resultSize.width() * ratio));
-    } else {
-        ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
-        float ratio = originalSize.width() / originalSize.height();
-        resultSize.setHeight(floorf(expectedSize.height()));
-        resultSize.setWidth(floorf(resultSize.height() * ratio));
-    }
-    return resultSize;
-}
-
-void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)
-{
-    if (m_domWindow) {
-        // Oilpan: the assumption is that FrameDestructionObserver::willDetachFrameHost()
-        // on LocalWindow will have signalled these frameWindowDiscarded() notifications.
-        //
-        // It is not invoked when finalizing the LocalFrame, as setDOMWindow() isn't
-        // performed (accessing the m_domWindow heap object is unsafe then.)
-        console().messageStorage()->frameWindowDiscarded(m_domWindow.get());
-        InspectorInstrumentation::frameWindowDiscarded(this, m_domWindow.get());
-    }
-    if (domWindow)
-        script().clearWindowProxy();
-    Frame::setDOMWindow(domWindow);
+    if (!client())
+        return;
+    m_loader.detach();
+    setView(nullptr);
+    willDetachFrameHost();
+    // Notify ScriptController that the frame is closing, since its cleanup ends up calling
+    // back to FrameLoaderClient via WindowProxy.
+    script().clearForClose();
+    InspectorInstrumentation::frameDetachedFromParent(this);
+    Frame::detach();
+#if ENABLE(OILPAN)
+    // Clear the FrameLoader right here rather than during
+    // finalization. Too late to access various heap objects at that
+    // stage.
+    loader().clear();
+#endif
 }
 
-void LocalFrame::didChangeVisibilityState()
+void LocalFrame::disconnectOwnerElement()
 {
-    if (document())
-        document()->didChangeVisibilityState();
-
-    WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > childFrames;
-    for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) {
-        if (child->isLocalFrame())
-            childFrames.append(toLocalFrame(child));
+    if (owner()) {
+        if (Document* document = this->document())
+            document->topDocument().clearAXObjectCache();
+#if ENABLE(OILPAN)
+        // First give the plugin elements holding persisted,
+        // renderer-less plugins the opportunity to dispose of them.
+        for (const auto& pluginElement : m_pluginElements)
+            pluginElement->disconnectContentFrame();
+        m_pluginElements.clear();
+#endif
     }
-
-    for (size_t i = 0; i < childFrames.size(); ++i)
-        childFrames[i]->didChangeVisibilityState();
+    Frame::disconnectOwnerElement();
 }
 
 void LocalFrame::addDestructionObserver(FrameDestructionObserver* observer)
@@ -314,16 +309,9 @@ void LocalFrame::removeDestructionObserver(FrameDestructionObserver* observer)
 
 void LocalFrame::willDetachFrameHost()
 {
-    // We should never be detatching the page during a Layout.
-    RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout());
-
-    Frame* parent = tree().parent();
-    if (parent && parent->isLocalFrame())
-        toLocalFrame(parent)->loader().checkLoadComplete();
 
-    WillBeHeapHashSet<RawPtrWillBeWeakMember<FrameDestructionObserver> >::iterator stop = m_destructionObservers.end();
-    for (WillBeHeapHashSet<RawPtrWillBeWeakMember<FrameDestructionObserver> >::iterator it = m_destructionObservers.begin(); it != stop; ++it)
-        (*it)->willDetachFrameHost();
+    for (const auto& frameDestructionObserver : m_destructionObservers)
+        frameDestructionObserver->willDetachFrameHost();
 
     // FIXME: Page should take care of updating focus/scrolling instead of Frame.
     // FIXME: It's unclear as to why this is called more than once, but it is,
@@ -336,44 +324,42 @@ void LocalFrame::willDetachFrameHost()
         page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
 }
 
-void LocalFrame::detachFromFrameHost()
-{
-    // We should never be detaching the page during a Layout.
-    RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout());
-    m_host = nullptr;
-}
-
-String LocalFrame::documentTypeString() const
+void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)
 {
-    if (DocumentType* doctype = document()->doctype())
-        return createMarkup(doctype);
-
-    return String();
-}
+    // Oilpan: setDOMWindow() cannot be used when finalizing. Which
+    // is acceptable as its actions are either not needed or handled
+    // by other means --
+    //
+    //  - FrameDestructionObserver::willDetachFrameHost() will have
+    //    signalled the Inspector frameWindowDiscarded() notifications.
+    //    We assume that all LocalFrames are detached, where that notification
+    //    will have been done.
+    //
+    //  - Calling LocalDOMWindow::reset() is not needed (called from
+    //    Frame::setDOMWindow().) The Member references it clears will now
+    //    die with the window. And the registered DOMWindowProperty instances that don't,
+    //    only keep a weak reference to this frame, so there's no need to be
+    //    explicitly notified that this frame is going away.
+    if (m_domWindow && host()) {
+        host()->consoleMessageStorage().frameWindowDiscarded(m_domWindow.get());
+        InspectorInstrumentation::frameWindowDiscarded(this, m_domWindow.get());
+    }
+    if (domWindow)
+        script().clearWindowProxy();
 
-String LocalFrame::selectedText() const
-{
-    return selection().selectedText();
+    if (m_domWindow)
+        m_domWindow->reset();
+    m_domWindow = domWindow;
 }
 
-String LocalFrame::selectedTextForClipboard() const
+Document* LocalFrame::document() const
 {
-    return selection().selectedTextForClipboard();
+    return m_domWindow ? m_domWindow->document() : 0;
 }
 
-VisiblePosition LocalFrame::visiblePositionForPoint(const IntPoint& framePoint)
+void LocalFrame::setPagePopupOwner(Element& owner)
 {
-    HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint);
-    Node* node = result.innerNonSharedNode();
-    if (!node)
-        return VisiblePosition();
-    RenderObject* renderer = node->renderer();
-    if (!renderer)
-        return VisiblePosition();
-    VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint()));
-    if (visiblePos.isNull())
-        visiblePos = VisiblePosition(firstPositionInOrBeforeNode(node));
-    return visiblePos;
+    m_pagePopupOwner = &owner;
 }
 
 RenderView* LocalFrame::contentRenderer() const
@@ -381,91 +367,42 @@ RenderView* LocalFrame::contentRenderer() const
     return document() ? document()->renderView() : 0;
 }
 
-Document* LocalFrame::document() const
-{
-    return m_domWindow ? m_domWindow->document() : 0;
-}
-
-Document* LocalFrame::documentAtPoint(const IntPoint& point)
-{
-    if (!view())
-        return 0;
-
-    IntPoint pt = view()->windowToContents(point);
-    HitTestResult result = HitTestResult(pt);
-
-    if (contentRenderer())
-        result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active);
-    return result.innerNode() ? &result.innerNode()->document() : 0;
-}
-
-PassRefPtrWillBeRawPtr<Range> LocalFrame::rangeForPoint(const IntPoint& framePoint)
+void LocalFrame::didChangeVisibilityState()
 {
-    VisiblePosition position = visiblePositionForPoint(framePoint);
-    if (position.isNull())
-        return nullptr;
-
-    VisiblePosition previous = position.previous();
-    if (previous.isNotNull()) {
-        RefPtrWillBeRawPtr<Range> previousCharacterRange = makeRange(previous, position);
-        LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
-        if (rect.contains(framePoint))
-            return previousCharacterRange.release();
-    }
+    if (document())
+        document()->didChangeVisibilityState();
 
-    VisiblePosition next = position.next();
-    if (RefPtrWillBeRawPtr<Range> nextCharacterRange = makeRange(position, next)) {
-        LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
-        if (rect.contains(framePoint))
-            return nextCharacterRange.release();
+    WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > childFrames;
+    for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) {
+        if (child->isLocalFrame())
+            childFrames.append(toLocalFrame(child));
     }
 
-    return nullptr;
+    for (size_t i = 0; i < childFrames.size(); ++i)
+        childFrames[i]->didChangeVisibilityState();
 }
 
-void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
-    ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
-    ScrollbarMode verticalScrollbarMode, bool verticalLock)
+LocalFrame* LocalFrame::localFrameRoot()
 {
-    ASSERT(this);
-    ASSERT(page());
-
-    bool isLocalRoot = this->isLocalRoot();
-
-    if (isLocalRoot && view())
-        view()->setParentVisible(false);
-
-    setView(nullptr);
-
-    RefPtr<FrameView> frameView;
-    if (isLocalRoot) {
-        frameView = FrameView::create(this, viewportSize);
-
-        // The layout size is set by WebViewImpl to support @viewport
-        frameView->setLayoutSizeFixedToFrameSize(false);
-    } else
-        frameView = FrameView::create(this);
-
-    frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
-
-    setView(frameView);
-
-    frameView->updateBackgroundRecursively(backgroundColor, transparent);
-
-    if (isLocalRoot)
-        frameView->setParentVisible(true);
-
-    // FIXME: Not clear what the right thing for OOPI is here.
-    if (ownerRenderer()) {
-        HTMLFrameOwnerElement* owner = deprecatedLocalOwner();
-        ASSERT(owner);
-        owner->setWidget(frameView);
-    }
+    LocalFrame* curFrame = this;
+    while (curFrame && curFrame->tree().parent() && curFrame->tree().parent()->isLocalFrame())
+        curFrame = toLocalFrame(curFrame->tree().parent());
 
-    if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner())
-        view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
+    return curFrame;
 }
 
+bool LocalFrame::inScope(TreeScope* scope) const
+{
+    ASSERT(scope);
+    Document* doc = document();
+    if (!doc)
+        return false;
+    // FIXME: This check is broken in for OOPI.
+    HTMLFrameOwnerElement* owner = doc->ownerElement();
+    if (!owner)
+        return false;
+    return owner->treeScope() == scope;
+}
 
 void LocalFrame::countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial)
 {
@@ -507,12 +444,55 @@ String LocalFrame::layerTreeAsText(LayerTreeFlags flags) const
     return textStream.release();
 }
 
-String LocalFrame::localLayerTreeAsText(unsigned flags) const
+void LocalFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio)
+{
+    // In setting printing, we should not validate resources already cached for the document.
+    // See https://bugs.webkit.org/show_bug.cgi?id=43704
+    ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher());
+
+    document()->setPrinting(printing);
+    view()->adjustMediaTypeForPrinting(printing);
+
+    document()->styleResolverChanged();
+    if (shouldUsePrintingLayout()) {
+        view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio);
+    } else {
+        view()->forceLayout();
+        view()->adjustViewSize();
+    }
+
+    // Subframes of the one we're printing don't lay out to the page size.
+    for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
+        if (child->isLocalFrame())
+            toLocalFrame(child.get())->setPrinting(printing, FloatSize(), FloatSize(), 0);
+    }
+}
+
+bool LocalFrame::shouldUsePrintingLayout() const
+{
+    // Only top frame being printed should be fit to page size.
+    // Subframes should be constrained by parents only.
+    return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing());
+}
+
+FloatSize LocalFrame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
 {
+    FloatSize resultSize;
     if (!contentRenderer())
-        return String();
+        return FloatSize();
 
-    return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags));
+    if (contentRenderer()->style()->isHorizontalWritingMode()) {
+        ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
+        float ratio = originalSize.height() / originalSize.width();
+        resultSize.setWidth(floorf(expectedSize.width()));
+        resultSize.setHeight(floorf(resultSize.width() * ratio));
+    } else {
+        ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
+        float ratio = originalSize.width() / originalSize.height();
+        resultSize.setHeight(floorf(expectedSize.height()));
+        resultSize.setWidth(floorf(resultSize.height() * ratio));
+    }
+    return resultSize;
 }
 
 void LocalFrame::setPageZoomFactor(float factor)
@@ -550,7 +530,7 @@ void LocalFrame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomF
             // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
             LayoutPoint scrollPosition = view->scrollPosition();
             float percentDifference = (pageZoomFactor / m_pageZoomFactor);
-            view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
+            view->setScrollPosition(DoublePoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
         }
     }
 
@@ -562,7 +542,7 @@ void LocalFrame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomF
             toLocalFrame(child.get())->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
     }
 
-    document->setNeedsStyleRecalc(SubtreeStyleChange);
+    document->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Zoom));
     document->updateLayoutIgnorePendingStylesheets();
 }
 
@@ -575,58 +555,23 @@ void LocalFrame::deviceOrPageScaleFactorChanged()
     }
 }
 
-bool LocalFrame::isURLAllowed(const KURL& url) const
+double LocalFrame::devicePixelRatio() const
 {
-    // We allow one level of self-reference because some sites depend on that,
-    // but we don't allow more than one.
-    if (page()->subframeCount() >= Page::maxNumberOfFrames)
-        return false;
-    bool foundSelfReference = false;
-    for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
-        if (!frame->isLocalFrame())
-            continue;
-        if (equalIgnoringFragmentIdentifier(toLocalFrame(frame)->document()->url(), url)) {
-            if (foundSelfReference)
-                return false;
-            foundSelfReference = true;
-        }
-    }
-    return true;
-}
+    if (!m_host)
+        return 0;
 
-bool LocalFrame::shouldReuseDefaultView(const KURL& url) const
-{
-    return loader().stateMachine()->isDisplayingInitialEmptyDocument() && document()->isSecureTransitionTo(url);
+    double ratio = m_host->deviceScaleFactor();
+    ratio *= pageZoomFactor();
+    return ratio;
 }
 
-void LocalFrame::removeSpellingMarkersUnderWords(const Vector<String>& words)
+String LocalFrame::documentTypeString() const
 {
-    spellChecker().removeSpellingMarkersUnderWords(words);
-}
-
-struct ScopedFramePaintingState {
-    ScopedFramePaintingState(LocalFrame* frame, Node* node)
-        : frame(frame)
-        , node(node)
-        , paintBehavior(frame->view()->paintBehavior())
-    {
-        ASSERT(!node || node->renderer());
-        if (node)
-            node->renderer()->updateDragState(true);
-    }
-
-    ~ScopedFramePaintingState()
-    {
-        if (node && node->renderer())
-            node->renderer()->updateDragState(false);
-        frame->view()->setPaintBehavior(paintBehavior);
-        frame->view()->setNodeToDraw(0);
-    }
+    if (DocumentType* doctype = document()->doctype())
+        return createMarkup(doctype);
 
-    LocalFrame* frame;
-    Node* node;
-    PaintBehavior paintBehavior;
-};
+    return String();
+}
 
 PassOwnPtr<DragImage> LocalFrame::nodeImage(Node& node)
 {
@@ -696,44 +641,157 @@ PassOwnPtr<DragImage> LocalFrame::dragImageForSelection()
     return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor);
 }
 
-double LocalFrame::devicePixelRatio() const
+String LocalFrame::selectedText() const
 {
-    if (!m_host)
+    return selection().selectedText();
+}
+
+String LocalFrame::selectedTextForClipboard() const
+{
+    return selection().selectedTextForClipboard();
+}
+
+VisiblePosition LocalFrame::visiblePositionForPoint(const IntPoint& framePoint)
+{
+    HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint);
+    Node* node = result.innerNonSharedNode();
+    if (!node)
+        return VisiblePosition();
+    RenderObject* renderer = node->renderer();
+    if (!renderer)
+        return VisiblePosition();
+    VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint()));
+    if (visiblePos.isNull())
+        visiblePos = VisiblePosition(firstPositionInOrBeforeNode(node));
+    return visiblePos;
+}
+
+Document* LocalFrame::documentAtPoint(const IntPoint& point)
+{
+    if (!view())
         return 0;
 
-    double ratio = m_host->deviceScaleFactor();
-    ratio *= pageZoomFactor();
-    return ratio;
+    IntPoint pt = view()->windowToContents(point);
+    HitTestResult result = HitTestResult(pt);
+
+    if (contentRenderer())
+        result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active);
+    return result.innerNode() ? &result.innerNode()->document() : 0;
 }
 
-void LocalFrame::disconnectOwnerElement()
+PassRefPtrWillBeRawPtr<Range> LocalFrame::rangeForPoint(const IntPoint& framePoint)
 {
-    if (owner()) {
-        if (Document* document = this->document())
-            document->topDocument().clearAXObjectCache();
+    VisiblePosition position = visiblePositionForPoint(framePoint);
+    if (position.isNull())
+        return nullptr;
+
+    VisiblePosition previous = position.previous();
+    if (previous.isNotNull()) {
+        RefPtrWillBeRawPtr<Range> previousCharacterRange = makeRange(previous, position);
+        LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
+        if (rect.contains(framePoint))
+            return previousCharacterRange.release();
+    }
+
+    VisiblePosition next = position.next();
+    if (RefPtrWillBeRawPtr<Range> nextCharacterRange = makeRange(position, next)) {
+        LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
+        if (rect.contains(framePoint))
+            return nextCharacterRange.release();
+    }
+
+    return nullptr;
+}
+
+bool LocalFrame::isURLAllowed(const KURL& url) const
+{
+    // We allow one level of self-reference because some sites depend on that,
+    // but we don't allow more than one.
+    if (host()->subframeCount() >= FrameHost::maxNumberOfFrames)
+        return false;
+    bool foundSelfReference = false;
+    for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
+        if (!frame->isLocalFrame())
+            continue;
+        if (equalIgnoringFragmentIdentifier(toLocalFrame(frame)->document()->url(), url)) {
+            if (foundSelfReference)
+                return false;
+            foundSelfReference = true;
+        }
+    }
+    return true;
+}
+
+bool LocalFrame::shouldReuseDefaultView(const KURL& url) const
+{
+    return loader().stateMachine()->isDisplayingInitialEmptyDocument() && document()->isSecureTransitionTo(url);
+}
+
+void LocalFrame::removeSpellingMarkersUnderWords(const Vector<String>& words)
+{
+    spellChecker().removeSpellingMarkersUnderWords(words);
+}
+
 #if ENABLE(OILPAN)
-        // Clear the FrameView and FrameLoader right here rather than
-        // during finalization. Too late to access various heap objects
-        // at that stage.
-        setView(nullptr);
-        loader().clear();
-#endif
+void LocalFrame::registerPluginElement(HTMLPlugInElement* plugin)
+{
+    m_pluginElements.add(plugin);
+}
+
+void LocalFrame::unregisterPluginElement(HTMLPlugInElement* plugin)
+{
+    ASSERT(m_pluginElements.contains(plugin));
+    m_pluginElements.remove(plugin);
+}
+
+void LocalFrame::clearWeakMembers(Visitor* visitor)
+{
+    Vector<HTMLPlugInElement*> deadPlugins;
+    for (const auto& pluginElement : m_pluginElements) {
+        if (!visitor->isAlive(pluginElement)) {
+            pluginElement->shouldDisposePlugin();
+            deadPlugins.append(pluginElement);
+        }
     }
-    Frame::disconnectOwnerElement();
+    for (unsigned i = 0; i < deadPlugins.size(); ++i)
+        m_pluginElements.remove(deadPlugins[i]);
 }
+#endif
 
-LocalFrame* LocalFrame::localFrameRoot()
+String LocalFrame::localLayerTreeAsText(unsigned flags) const
 {
-    LocalFrame* curFrame = this;
-    while (curFrame && curFrame->tree().parent() && curFrame->tree().parent()->isLocalFrame())
-        curFrame = toLocalFrame(curFrame->tree().parent());
+    if (!contentRenderer())
+        return String();
 
-    return curFrame;
+    return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags));
 }
 
-void LocalFrame::setPagePopupOwner(Element& owner)
+inline LocalFrame::LocalFrame(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
+    : Frame(client, host, owner)
+    , m_loader(this)
+    , m_navigationScheduler(this)
+    , m_script(ScriptController::create(this))
+    , m_editor(Editor::create(*this))
+    , m_spellChecker(SpellChecker::create(*this))
+    , m_selection(FrameSelection::create(this))
+    , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this)))
+    , m_console(FrameConsole::create(*this))
+    , m_inputMethodController(InputMethodController::create(*this))
+    , m_pageZoomFactor(parentPageZoomFactor(this))
+    , m_textZoomFactor(parentTextZoomFactor(this))
+    , m_inViewSourceMode(false)
 {
-    m_pagePopupOwner = &owner;
+}
+
+void LocalFrame::detachView()
+{
+    // We detach the FrameView's custom scroll bars as early as
+    // possible to prevent m_doc->detach() from messing with the view
+    // such that its scroll bars won't be torn down.
+    //
+    // FIXME: We should revisit this.
+    if (m_view)
+        m_view->prepareForDetach();
 }
 
 } // namespace blink