Home | History | Annotate | Download | only in frame
      1 /*
      2  * Copyright (C) 1998, 1999 Torben Weis <weis (at) kde.org>
      3  *                     1999 Lars Knoll <knoll (at) kde.org>
      4  *                     1999 Antti Koivisto <koivisto (at) kde.org>
      5  *                     2000 Simon Hausmann <hausmann (at) kde.org>
      6  *                     2000 Stefan Schimanski <1Stein (at) gmx.de>
      7  *                     2001 George Staikos <staikos (at) kde.org>
      8  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      9  * Copyright (C) 2005 Alexey Proskuryakov <ap (at) nypop.com>
     10  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
     11  * Copyright (C) 2008 Eric Seidel <eric (at) webkit.org>
     12  * Copyright (C) 2008 Google Inc.
     13  *
     14  * This library is free software; you can redistribute it and/or
     15  * modify it under the terms of the GNU Library General Public
     16  * License as published by the Free Software Foundation; either
     17  * version 2 of the License, or (at your option) any later version.
     18  *
     19  * This library is distributed in the hope that it will be useful,
     20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     22  * Library General Public License for more details.
     23  *
     24  * You should have received a copy of the GNU Library General Public License
     25  * along with this library; see the file COPYING.LIB.  If not, write to
     26  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     27  * Boston, MA 02110-1301, USA.
     28  */
     29 
     30 #include "config.h"
     31 #include "core/frame/LocalFrame.h"
     32 
     33 #include "bindings/core/v8/ScriptController.h"
     34 #include "core/dom/DocumentType.h"
     35 #include "core/editing/Editor.h"
     36 #include "core/editing/FrameSelection.h"
     37 #include "core/editing/InputMethodController.h"
     38 #include "core/editing/SpellChecker.h"
     39 #include "core/editing/htmlediting.h"
     40 #include "core/editing/markup.h"
     41 #include "core/events/Event.h"
     42 #include "core/fetch/ResourceFetcher.h"
     43 #include "core/frame/EventHandlerRegistry.h"
     44 #include "core/frame/FrameConsole.h"
     45 #include "core/frame/FrameDestructionObserver.h"
     46 #include "core/frame/FrameHost.h"
     47 #include "core/frame/FrameView.h"
     48 #include "core/frame/LocalDOMWindow.h"
     49 #include "core/frame/Settings.h"
     50 #include "core/html/HTMLFrameElementBase.h"
     51 #include "core/inspector/ConsoleMessageStorage.h"
     52 #include "core/inspector/InspectorInstrumentation.h"
     53 #include "core/loader/FrameLoaderClient.h"
     54 #include "core/page/Chrome.h"
     55 #include "core/page/EventHandler.h"
     56 #include "core/page/FocusController.h"
     57 #include "core/page/Page.h"
     58 #include "core/page/scrolling/ScrollingCoordinator.h"
     59 #include "core/rendering/HitTestResult.h"
     60 #include "core/rendering/RenderLayer.h"
     61 #include "core/rendering/RenderView.h"
     62 #include "core/rendering/compositing/RenderLayerCompositor.h"
     63 #include "core/svg/SVGDocumentExtensions.h"
     64 #include "platform/DragImage.h"
     65 #include "platform/RuntimeEnabledFeatures.h"
     66 #include "platform/graphics/GraphicsContext.h"
     67 #include "platform/graphics/ImageBuffer.h"
     68 #include "platform/text/TextStream.h"
     69 #include "wtf/PassOwnPtr.h"
     70 #include "wtf/StdLibExtras.h"
     71 
     72 namespace blink {
     73 
     74 using namespace HTMLNames;
     75 
     76 static inline float parentPageZoomFactor(LocalFrame* frame)
     77 {
     78     Frame* parent = frame->tree().parent();
     79     if (!parent || !parent->isLocalFrame())
     80         return 1;
     81     return toLocalFrame(parent)->pageZoomFactor();
     82 }
     83 
     84 static inline float parentTextZoomFactor(LocalFrame* frame)
     85 {
     86     Frame* parent = frame->tree().parent();
     87     if (!parent || !parent->isLocalFrame())
     88         return 1;
     89     return toLocalFrame(parent)->textZoomFactor();
     90 }
     91 
     92 inline LocalFrame::LocalFrame(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
     93     : Frame(client, host, owner)
     94     , m_loader(this)
     95     , m_navigationScheduler(this)
     96     , m_script(adoptPtr(new ScriptController(this)))
     97     , m_editor(Editor::create(*this))
     98     , m_spellChecker(SpellChecker::create(*this))
     99     , m_selection(FrameSelection::create(this))
    100     , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this)))
    101     , m_console(FrameConsole::create(*this))
    102     , m_inputMethodController(InputMethodController::create(*this))
    103     , m_pageZoomFactor(parentPageZoomFactor(this))
    104     , m_textZoomFactor(parentTextZoomFactor(this))
    105     , m_inViewSourceMode(false)
    106 {
    107 }
    108 
    109 PassRefPtrWillBeRawPtr<LocalFrame> LocalFrame::create(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
    110 {
    111     RefPtrWillBeRawPtr<LocalFrame> frame = adoptRefWillBeNoop(new LocalFrame(client, host, owner));
    112     InspectorInstrumentation::frameAttachedToParent(frame.get());
    113     return frame.release();
    114 }
    115 
    116 LocalFrame::~LocalFrame()
    117 {
    118 #if ENABLE(OILPAN)
    119     // Verify that the FrameView has been cleared as part of detaching
    120     // the frame owner.
    121     ASSERT(!m_view);
    122     // Oilpan: see setDOMWindow() comment why it is acceptable not to
    123     // mirror the non-Oilpan call below.
    124     //
    125     // Also, FrameDestructionObservers that live longer than this
    126     // frame object keep weak references to the frame; those will be
    127     // automatically cleared by the garbage collector. Hence, explicit
    128     // frameDestroyed() notifications aren't needed.
    129 #else
    130     // FIXME: follow Oilpan and clear the FrameView and FrameLoader
    131     // during FrameOwner detachment instead, see LocalFrame::disconnectOwnerElement().
    132     setView(nullptr);
    133     m_loader.clear();
    134     setDOMWindow(nullptr);
    135 
    136     HashSet<RawPtr<FrameDestructionObserver> >::iterator stop = m_destructionObservers.end();
    137     for (HashSet<RawPtr<FrameDestructionObserver> >::iterator it = m_destructionObservers.begin(); it != stop; ++it)
    138         (*it)->frameDestroyed();
    139 #endif
    140 }
    141 
    142 void LocalFrame::trace(Visitor* visitor)
    143 {
    144 #if ENABLE(OILPAN)
    145     visitor->trace(m_destructionObservers);
    146     visitor->trace(m_loader);
    147     visitor->trace(m_navigationScheduler);
    148     visitor->trace(m_pagePopupOwner);
    149     visitor->trace(m_editor);
    150     visitor->trace(m_spellChecker);
    151     visitor->trace(m_selection);
    152     visitor->trace(m_eventHandler);
    153     visitor->trace(m_console);
    154     visitor->trace(m_inputMethodController);
    155     HeapSupplementable<LocalFrame>::trace(visitor);
    156 #endif
    157     Frame::trace(visitor);
    158 }
    159 
    160 void LocalFrame::detach()
    161 {
    162     // A lot of the following steps can result in the current frame being
    163     // detached, so protect a reference to it.
    164     RefPtrWillBeRawPtr<LocalFrame> protect(this);
    165     m_loader.stopAllLoaders();
    166     m_loader.closeURL();
    167     detachChildren();
    168     // stopAllLoaders() needs to be called after detachChildren(), because detachChildren()
    169     // will trigger the unload event handlers of any child frames, and those event
    170     // handlers might start a new subresource load in this frame.
    171     m_loader.stopAllLoaders();
    172     m_loader.detachFromParent();
    173 }
    174 
    175 bool LocalFrame::inScope(TreeScope* scope) const
    176 {
    177     ASSERT(scope);
    178     Document* doc = document();
    179     if (!doc)
    180         return false;
    181     // FIXME: This check is broken in for OOPI.
    182     HTMLFrameOwnerElement* owner = doc->ownerElement();
    183     if (!owner)
    184         return false;
    185     return owner->treeScope() == scope;
    186 }
    187 
    188 void LocalFrame::detachView()
    189 {
    190     // We detach the FrameView's custom scroll bars as early as
    191     // possible to prevent m_doc->detach() from messing with the view
    192     // such that its scroll bars won't be torn down.
    193     //
    194     // FIXME: We should revisit this.
    195     if (m_view)
    196         m_view->prepareForDetach();
    197 }
    198 
    199 void LocalFrame::setView(PassRefPtr<FrameView> view)
    200 {
    201     detachView();
    202 
    203     // Prepare for destruction now, so any unload event handlers get run and the LocalDOMWindow is
    204     // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
    205     // these calls to work.
    206     if (!view && document() && document()->isActive()) {
    207         // FIXME: We don't call willRemove here. Why is that OK?
    208         document()->prepareForDestruction();
    209     }
    210 
    211     eventHandler().clear();
    212 
    213     m_view = view;
    214 
    215     if (m_view && isMainFrame()) {
    216         if (settings()->pinchVirtualViewportEnabled())
    217             m_host->pinchViewport().mainFrameDidChangeSize();
    218         else
    219             m_view->setVisibleContentScaleFactor(page()->pageScaleFactor());
    220     }
    221 }
    222 
    223 void LocalFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio)
    224 {
    225     // In setting printing, we should not validate resources already cached for the document.
    226     // See https://bugs.webkit.org/show_bug.cgi?id=43704
    227     ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher());
    228 
    229     document()->setPrinting(printing);
    230     view()->adjustMediaTypeForPrinting(printing);
    231 
    232     document()->styleResolverChanged();
    233     if (shouldUsePrintingLayout()) {
    234         view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio);
    235     } else {
    236         view()->forceLayout();
    237         view()->adjustViewSize();
    238     }
    239 
    240     // Subframes of the one we're printing don't lay out to the page size.
    241     for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
    242         if (child->isLocalFrame())
    243             toLocalFrame(child.get())->setPrinting(printing, FloatSize(), FloatSize(), 0);
    244     }
    245 }
    246 
    247 bool LocalFrame::shouldUsePrintingLayout() const
    248 {
    249     // Only top frame being printed should be fit to page size.
    250     // Subframes should be constrained by parents only.
    251     return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing());
    252 }
    253 
    254 FloatSize LocalFrame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
    255 {
    256     FloatSize resultSize;
    257     if (!contentRenderer())
    258         return FloatSize();
    259 
    260     if (contentRenderer()->style()->isHorizontalWritingMode()) {
    261         ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
    262         float ratio = originalSize.height() / originalSize.width();
    263         resultSize.setWidth(floorf(expectedSize.width()));
    264         resultSize.setHeight(floorf(resultSize.width() * ratio));
    265     } else {
    266         ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
    267         float ratio = originalSize.width() / originalSize.height();
    268         resultSize.setHeight(floorf(expectedSize.height()));
    269         resultSize.setWidth(floorf(resultSize.height() * ratio));
    270     }
    271     return resultSize;
    272 }
    273 
    274 void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)
    275 {
    276     if (m_domWindow) {
    277         // Oilpan: the assumption is that FrameDestructionObserver::willDetachFrameHost()
    278         // on LocalWindow will have signalled these frameWindowDiscarded() notifications.
    279         //
    280         // It is not invoked when finalizing the LocalFrame, as setDOMWindow() isn't
    281         // performed (accessing the m_domWindow heap object is unsafe then.)
    282         console().messageStorage()->frameWindowDiscarded(m_domWindow.get());
    283         InspectorInstrumentation::frameWindowDiscarded(this, m_domWindow.get());
    284     }
    285     if (domWindow)
    286         script().clearWindowProxy();
    287     Frame::setDOMWindow(domWindow);
    288 }
    289 
    290 void LocalFrame::didChangeVisibilityState()
    291 {
    292     if (document())
    293         document()->didChangeVisibilityState();
    294 
    295     WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > childFrames;
    296     for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) {
    297         if (child->isLocalFrame())
    298             childFrames.append(toLocalFrame(child));
    299     }
    300 
    301     for (size_t i = 0; i < childFrames.size(); ++i)
    302         childFrames[i]->didChangeVisibilityState();
    303 }
    304 
    305 void LocalFrame::addDestructionObserver(FrameDestructionObserver* observer)
    306 {
    307     m_destructionObservers.add(observer);
    308 }
    309 
    310 void LocalFrame::removeDestructionObserver(FrameDestructionObserver* observer)
    311 {
    312     m_destructionObservers.remove(observer);
    313 }
    314 
    315 void LocalFrame::willDetachFrameHost()
    316 {
    317     // We should never be detatching the page during a Layout.
    318     RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout());
    319 
    320     Frame* parent = tree().parent();
    321     if (parent && parent->isLocalFrame())
    322         toLocalFrame(parent)->loader().checkLoadComplete();
    323 
    324     WillBeHeapHashSet<RawPtrWillBeWeakMember<FrameDestructionObserver> >::iterator stop = m_destructionObservers.end();
    325     for (WillBeHeapHashSet<RawPtrWillBeWeakMember<FrameDestructionObserver> >::iterator it = m_destructionObservers.begin(); it != stop; ++it)
    326         (*it)->willDetachFrameHost();
    327 
    328     // FIXME: Page should take care of updating focus/scrolling instead of Frame.
    329     // FIXME: It's unclear as to why this is called more than once, but it is,
    330     // so page() could be null.
    331     if (page() && page()->focusController().focusedFrame() == this)
    332         page()->focusController().setFocusedFrame(nullptr);
    333     script().clearScriptObjects();
    334 
    335     if (page() && page()->scrollingCoordinator() && m_view)
    336         page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
    337 }
    338 
    339 void LocalFrame::detachFromFrameHost()
    340 {
    341     // We should never be detaching the page during a Layout.
    342     RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout());
    343     m_host = nullptr;
    344 }
    345 
    346 String LocalFrame::documentTypeString() const
    347 {
    348     if (DocumentType* doctype = document()->doctype())
    349         return createMarkup(doctype);
    350 
    351     return String();
    352 }
    353 
    354 String LocalFrame::selectedText() const
    355 {
    356     return selection().selectedText();
    357 }
    358 
    359 String LocalFrame::selectedTextForClipboard() const
    360 {
    361     return selection().selectedTextForClipboard();
    362 }
    363 
    364 VisiblePosition LocalFrame::visiblePositionForPoint(const IntPoint& framePoint)
    365 {
    366     HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint);
    367     Node* node = result.innerNonSharedNode();
    368     if (!node)
    369         return VisiblePosition();
    370     RenderObject* renderer = node->renderer();
    371     if (!renderer)
    372         return VisiblePosition();
    373     VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint()));
    374     if (visiblePos.isNull())
    375         visiblePos = VisiblePosition(firstPositionInOrBeforeNode(node));
    376     return visiblePos;
    377 }
    378 
    379 RenderView* LocalFrame::contentRenderer() const
    380 {
    381     return document() ? document()->renderView() : 0;
    382 }
    383 
    384 Document* LocalFrame::document() const
    385 {
    386     return m_domWindow ? m_domWindow->document() : 0;
    387 }
    388 
    389 Document* LocalFrame::documentAtPoint(const IntPoint& point)
    390 {
    391     if (!view())
    392         return 0;
    393 
    394     IntPoint pt = view()->windowToContents(point);
    395     HitTestResult result = HitTestResult(pt);
    396 
    397     if (contentRenderer())
    398         result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active);
    399     return result.innerNode() ? &result.innerNode()->document() : 0;
    400 }
    401 
    402 PassRefPtrWillBeRawPtr<Range> LocalFrame::rangeForPoint(const IntPoint& framePoint)
    403 {
    404     VisiblePosition position = visiblePositionForPoint(framePoint);
    405     if (position.isNull())
    406         return nullptr;
    407 
    408     VisiblePosition previous = position.previous();
    409     if (previous.isNotNull()) {
    410         RefPtrWillBeRawPtr<Range> previousCharacterRange = makeRange(previous, position);
    411         LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
    412         if (rect.contains(framePoint))
    413             return previousCharacterRange.release();
    414     }
    415 
    416     VisiblePosition next = position.next();
    417     if (RefPtrWillBeRawPtr<Range> nextCharacterRange = makeRange(position, next)) {
    418         LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
    419         if (rect.contains(framePoint))
    420             return nextCharacterRange.release();
    421     }
    422 
    423     return nullptr;
    424 }
    425 
    426 void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
    427     ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
    428     ScrollbarMode verticalScrollbarMode, bool verticalLock)
    429 {
    430     ASSERT(this);
    431     ASSERT(page());
    432 
    433     bool isLocalRoot = this->isLocalRoot();
    434 
    435     if (isLocalRoot && view())
    436         view()->setParentVisible(false);
    437 
    438     setView(nullptr);
    439 
    440     RefPtr<FrameView> frameView;
    441     if (isLocalRoot) {
    442         frameView = FrameView::create(this, viewportSize);
    443 
    444         // The layout size is set by WebViewImpl to support @viewport
    445         frameView->setLayoutSizeFixedToFrameSize(false);
    446     } else
    447         frameView = FrameView::create(this);
    448 
    449     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
    450 
    451     setView(frameView);
    452 
    453     frameView->updateBackgroundRecursively(backgroundColor, transparent);
    454 
    455     if (isLocalRoot)
    456         frameView->setParentVisible(true);
    457 
    458     // FIXME: Not clear what the right thing for OOPI is here.
    459     if (ownerRenderer()) {
    460         HTMLFrameOwnerElement* owner = deprecatedLocalOwner();
    461         ASSERT(owner);
    462         owner->setWidget(frameView);
    463     }
    464 
    465     if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner())
    466         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
    467 }
    468 
    469 
    470 void LocalFrame::countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial)
    471 {
    472     RenderObject* root = view()->layoutRoot();
    473     isPartial = true;
    474     if (!root) {
    475         isPartial = false;
    476         root = contentRenderer();
    477     }
    478 
    479     needsLayoutObjects = 0;
    480     totalObjects = 0;
    481 
    482     for (RenderObject* o = root; o; o = o->nextInPreOrder(root)) {
    483         ++totalObjects;
    484         if (o->needsLayout())
    485             ++needsLayoutObjects;
    486     }
    487 }
    488 
    489 String LocalFrame::layerTreeAsText(LayerTreeFlags flags) const
    490 {
    491     TextStream textStream;
    492     textStream << localLayerTreeAsText(flags);
    493 
    494     for (Frame* child = tree().firstChild(); child; child = child->tree().traverseNext(this)) {
    495         if (!child->isLocalFrame())
    496             continue;
    497         String childLayerTree = toLocalFrame(child)->localLayerTreeAsText(flags);
    498         if (!childLayerTree.length())
    499             continue;
    500 
    501         textStream << "\n\n--------\nFrame: '";
    502         textStream << child->tree().uniqueName();
    503         textStream << "'\n--------\n";
    504         textStream << childLayerTree;
    505     }
    506 
    507     return textStream.release();
    508 }
    509 
    510 String LocalFrame::localLayerTreeAsText(unsigned flags) const
    511 {
    512     if (!contentRenderer())
    513         return String();
    514 
    515     return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags));
    516 }
    517 
    518 void LocalFrame::setPageZoomFactor(float factor)
    519 {
    520     setPageAndTextZoomFactors(factor, m_textZoomFactor);
    521 }
    522 
    523 void LocalFrame::setTextZoomFactor(float factor)
    524 {
    525     setPageAndTextZoomFactors(m_pageZoomFactor, factor);
    526 }
    527 
    528 void LocalFrame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
    529 {
    530     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
    531         return;
    532 
    533     Page* page = this->page();
    534     if (!page)
    535         return;
    536 
    537     Document* document = this->document();
    538     if (!document)
    539         return;
    540 
    541     // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
    542     // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
    543     if (document->isSVGDocument()) {
    544         if (!document->accessSVGExtensions().zoomAndPanEnabled())
    545             return;
    546     }
    547 
    548     if (m_pageZoomFactor != pageZoomFactor) {
    549         if (FrameView* view = this->view()) {
    550             // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
    551             LayoutPoint scrollPosition = view->scrollPosition();
    552             float percentDifference = (pageZoomFactor / m_pageZoomFactor);
    553             view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
    554         }
    555     }
    556 
    557     m_pageZoomFactor = pageZoomFactor;
    558     m_textZoomFactor = textZoomFactor;
    559 
    560     for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
    561         if (child->isLocalFrame())
    562             toLocalFrame(child.get())->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
    563     }
    564 
    565     document->setNeedsStyleRecalc(SubtreeStyleChange);
    566     document->updateLayoutIgnorePendingStylesheets();
    567 }
    568 
    569 void LocalFrame::deviceOrPageScaleFactorChanged()
    570 {
    571     document()->mediaQueryAffectingValueChanged();
    572     for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
    573         if (child->isLocalFrame())
    574             toLocalFrame(child.get())->deviceOrPageScaleFactorChanged();
    575     }
    576 }
    577 
    578 bool LocalFrame::isURLAllowed(const KURL& url) const
    579 {
    580     // We allow one level of self-reference because some sites depend on that,
    581     // but we don't allow more than one.
    582     if (page()->subframeCount() >= Page::maxNumberOfFrames)
    583         return false;
    584     bool foundSelfReference = false;
    585     for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
    586         if (!frame->isLocalFrame())
    587             continue;
    588         if (equalIgnoringFragmentIdentifier(toLocalFrame(frame)->document()->url(), url)) {
    589             if (foundSelfReference)
    590                 return false;
    591             foundSelfReference = true;
    592         }
    593     }
    594     return true;
    595 }
    596 
    597 bool LocalFrame::shouldReuseDefaultView(const KURL& url) const
    598 {
    599     return loader().stateMachine()->isDisplayingInitialEmptyDocument() && document()->isSecureTransitionTo(url);
    600 }
    601 
    602 void LocalFrame::removeSpellingMarkersUnderWords(const Vector<String>& words)
    603 {
    604     spellChecker().removeSpellingMarkersUnderWords(words);
    605 }
    606 
    607 struct ScopedFramePaintingState {
    608     ScopedFramePaintingState(LocalFrame* frame, Node* node)
    609         : frame(frame)
    610         , node(node)
    611         , paintBehavior(frame->view()->paintBehavior())
    612     {
    613         ASSERT(!node || node->renderer());
    614         if (node)
    615             node->renderer()->updateDragState(true);
    616     }
    617 
    618     ~ScopedFramePaintingState()
    619     {
    620         if (node && node->renderer())
    621             node->renderer()->updateDragState(false);
    622         frame->view()->setPaintBehavior(paintBehavior);
    623         frame->view()->setNodeToDraw(0);
    624     }
    625 
    626     LocalFrame* frame;
    627     Node* node;
    628     PaintBehavior paintBehavior;
    629 };
    630 
    631 PassOwnPtr<DragImage> LocalFrame::nodeImage(Node& node)
    632 {
    633     if (!node.renderer())
    634         return nullptr;
    635 
    636     const ScopedFramePaintingState state(this, &node);
    637 
    638     m_view->updateLayoutAndStyleForPainting();
    639 
    640     m_view->setPaintBehavior(state.paintBehavior | PaintBehaviorFlattenCompositingLayers);
    641 
    642     m_view->setNodeToDraw(&node); // Enable special sub-tree drawing mode.
    643 
    644     // Document::updateLayout may have blown away the original RenderObject.
    645     RenderObject* renderer = node.renderer();
    646     if (!renderer)
    647         return nullptr;
    648 
    649     LayoutRect topLevelRect;
    650     IntRect paintingRect = pixelSnappedIntRect(renderer->paintingRootRect(topLevelRect));
    651 
    652     ASSERT(document()->isActive());
    653     float deviceScaleFactor = m_host->deviceScaleFactor();
    654     paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
    655     paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
    656 
    657     OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size());
    658     if (!buffer)
    659         return nullptr;
    660     buffer->context()->scale(deviceScaleFactor, deviceScaleFactor);
    661     buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
    662     buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
    663 
    664     m_view->paintContents(buffer->context(), paintingRect);
    665 
    666     RefPtr<Image> image = buffer->copyImage();
    667     return DragImage::create(image.get(), renderer->shouldRespectImageOrientation(), deviceScaleFactor);
    668 }
    669 
    670 PassOwnPtr<DragImage> LocalFrame::dragImageForSelection()
    671 {
    672     if (!selection().isRange())
    673         return nullptr;
    674 
    675     const ScopedFramePaintingState state(this, 0);
    676     m_view->setPaintBehavior(PaintBehaviorSelectionOnly | PaintBehaviorFlattenCompositingLayers);
    677     m_view->updateLayoutAndStyleForPainting();
    678 
    679     IntRect paintingRect = enclosingIntRect(selection().bounds());
    680 
    681     ASSERT(document()->isActive());
    682     float deviceScaleFactor = m_host->deviceScaleFactor();
    683     paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
    684     paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
    685 
    686     OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size());
    687     if (!buffer)
    688         return nullptr;
    689     buffer->context()->scale(deviceScaleFactor, deviceScaleFactor);
    690     buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
    691     buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
    692 
    693     m_view->paintContents(buffer->context(), paintingRect);
    694 
    695     RefPtr<Image> image = buffer->copyImage();
    696     return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor);
    697 }
    698 
    699 double LocalFrame::devicePixelRatio() const
    700 {
    701     if (!m_host)
    702         return 0;
    703 
    704     double ratio = m_host->deviceScaleFactor();
    705     ratio *= pageZoomFactor();
    706     return ratio;
    707 }
    708 
    709 void LocalFrame::disconnectOwnerElement()
    710 {
    711     if (owner()) {
    712         if (Document* document = this->document())
    713             document->topDocument().clearAXObjectCache();
    714 #if ENABLE(OILPAN)
    715         // Clear the FrameView and FrameLoader right here rather than
    716         // during finalization. Too late to access various heap objects
    717         // at that stage.
    718         setView(nullptr);
    719         loader().clear();
    720 #endif
    721     }
    722     Frame::disconnectOwnerElement();
    723 }
    724 
    725 LocalFrame* LocalFrame::localFrameRoot()
    726 {
    727     LocalFrame* curFrame = this;
    728     while (curFrame && curFrame->tree().parent() && curFrame->tree().parent()->isLocalFrame())
    729         curFrame = toLocalFrame(curFrame->tree().parent());
    730 
    731     return curFrame;
    732 }
    733 
    734 void LocalFrame::setPagePopupOwner(Element& owner)
    735 {
    736     m_pagePopupOwner = &owner;
    737 }
    738 
    739 } // namespace blink
    740