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/Frame.h"
     32 
     33 #include "RuntimeEnabledFeatures.h"
     34 #include "bindings/v8/ScriptController.h"
     35 #include "core/dom/DocumentType.h"
     36 #include "core/dom/WheelController.h"
     37 #include "core/editing/Editor.h"
     38 #include "core/editing/FrameSelection.h"
     39 #include "core/editing/InputMethodController.h"
     40 #include "core/editing/SpellChecker.h"
     41 #include "core/editing/htmlediting.h"
     42 #include "core/editing/markup.h"
     43 #include "core/events/Event.h"
     44 #include "core/fetch/ResourceFetcher.h"
     45 #include "core/frame/DOMWindow.h"
     46 #include "core/frame/FrameDestructionObserver.h"
     47 #include "core/frame/FrameView.h"
     48 #include "core/frame/Settings.h"
     49 #include "core/frame/animation/AnimationController.h"
     50 #include "core/html/HTMLFrameElementBase.h"
     51 #include "core/inspector/InspectorInstrumentation.h"
     52 #include "core/loader/EmptyClients.h"
     53 #include "core/loader/FrameLoaderClient.h"
     54 #include "core/page/Chrome.h"
     55 #include "core/page/ChromeClient.h"
     56 #include "core/page/EventHandler.h"
     57 #include "core/page/FocusController.h"
     58 #include "core/page/Page.h"
     59 #include "core/page/scrolling/ScrollingCoordinator.h"
     60 #include "core/platform/DragImage.h"
     61 #include "core/rendering/HitTestResult.h"
     62 #include "core/rendering/RenderLayerCompositor.h"
     63 #include "core/rendering/RenderPart.h"
     64 #include "core/rendering/RenderView.h"
     65 #include "core/svg/SVGDocument.h"
     66 #include "platform/graphics/GraphicsContext.h"
     67 #include "platform/graphics/ImageBuffer.h"
     68 #include "public/platform/WebLayer.h"
     69 #include "wtf/PassOwnPtr.h"
     70 #include "wtf/RefCountedLeakCounter.h"
     71 #include "wtf/StdLibExtras.h"
     72 
     73 using namespace std;
     74 
     75 namespace WebCore {
     76 
     77 using namespace HTMLNames;
     78 
     79 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame"));
     80 
     81 static inline Frame* parentFromOwnerElement(HTMLFrameOwnerElement* ownerElement)
     82 {
     83     if (!ownerElement)
     84         return 0;
     85     return ownerElement->document().frame();
     86 }
     87 
     88 static inline float parentPageZoomFactor(Frame* frame)
     89 {
     90     Frame* parent = frame->tree().parent();
     91     if (!parent)
     92         return 1;
     93     return parent->pageZoomFactor();
     94 }
     95 
     96 static inline float parentTextZoomFactor(Frame* frame)
     97 {
     98     Frame* parent = frame->tree().parent();
     99     if (!parent)
    100         return 1;
    101     return parent->textZoomFactor();
    102 }
    103 
    104 inline Frame::Frame(PassRefPtr<FrameInit> frameInit)
    105     : m_page(frameInit->page())
    106     , m_treeNode(this, parentFromOwnerElement(frameInit->ownerElement()))
    107     , m_loader(this, frameInit->frameLoaderClient())
    108     , m_navigationScheduler(this)
    109     , m_script(adoptPtr(new ScriptController(this)))
    110     , m_editor(Editor::create(*this))
    111     , m_spellChecker(SpellChecker::create(*this))
    112     , m_selection(adoptPtr(new FrameSelection(this)))
    113     , m_eventHandler(adoptPtr(new EventHandler(this)))
    114     , m_animationController(adoptPtr(new AnimationController(this)))
    115     , m_inputMethodController(InputMethodController::create(*this))
    116     , m_frameInit(frameInit)
    117     , m_pageZoomFactor(parentPageZoomFactor(this))
    118     , m_textZoomFactor(parentTextZoomFactor(this))
    119 #if ENABLE(ORIENTATION_EVENTS)
    120     , m_orientation(0)
    121 #endif
    122     , m_inViewSourceMode(false)
    123     , m_remotePlatformLayer(0)
    124 {
    125     ASSERT(m_page);
    126 
    127     if (ownerElement()) {
    128         m_page->incrementSubframeCount();
    129         ownerElement()->setContentFrame(*this);
    130     }
    131 
    132 #ifndef NDEBUG
    133     frameCounter.increment();
    134 #endif
    135 }
    136 
    137 PassRefPtr<Frame> Frame::create(PassRefPtr<FrameInit> frameInit)
    138 {
    139     RefPtr<Frame> frame = adoptRef(new Frame(frameInit));
    140     if (!frame->ownerElement())
    141         frame->page()->setMainFrame(frame);
    142     InspectorInstrumentation::frameAttachedToParent(frame.get());
    143     return frame.release();
    144 }
    145 
    146 Frame::~Frame()
    147 {
    148     setView(0);
    149     loader().clear(ClearScriptObjects | ClearWindowObject);
    150 
    151     // FIXME: We should not be doing all this work inside the destructor
    152 
    153 #ifndef NDEBUG
    154     frameCounter.decrement();
    155 #endif
    156 
    157     disconnectOwnerElement();
    158 
    159     HashSet<FrameDestructionObserver*>::iterator stop = m_destructionObservers.end();
    160     for (HashSet<FrameDestructionObserver*>::iterator it = m_destructionObservers.begin(); it != stop; ++it)
    161         (*it)->frameDestroyed();
    162 }
    163 
    164 bool Frame::inScope(TreeScope* scope) const
    165 {
    166     ASSERT(scope);
    167     Document* doc = document();
    168     if (!doc)
    169         return false;
    170     HTMLFrameOwnerElement* owner = doc->ownerElement();
    171     if (!owner)
    172         return false;
    173     return owner->treeScope() == scope;
    174 }
    175 
    176 void Frame::addDestructionObserver(FrameDestructionObserver* observer)
    177 {
    178     m_destructionObservers.add(observer);
    179 }
    180 
    181 void Frame::removeDestructionObserver(FrameDestructionObserver* observer)
    182 {
    183     m_destructionObservers.remove(observer);
    184 }
    185 
    186 void Frame::setView(PassRefPtr<FrameView> view)
    187 {
    188     // We the custom scroll bars as early as possible to prevent m_doc->detach()
    189     // from messing with the view such that its scroll bars won't be torn down.
    190     // FIXME: We should revisit this.
    191     if (m_view)
    192         m_view->prepareForDetach();
    193 
    194     // Prepare for destruction now, so any unload event handlers get run and the DOMWindow is
    195     // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
    196     // these calls to work.
    197     if (!view && document() && document()->isActive()) {
    198         // FIXME: We don't call willRemove here. Why is that OK?
    199         document()->prepareForDestruction();
    200     }
    201 
    202     if (m_view)
    203         m_view->unscheduleRelayout();
    204 
    205     eventHandler().clear();
    206 
    207     m_view = view;
    208 
    209     if (m_view && isMainFrame())
    210         m_view->setVisibleContentScaleFactor(m_page->pageScaleFactor());
    211 }
    212 
    213 #if ENABLE(ORIENTATION_EVENTS)
    214 void Frame::sendOrientationChangeEvent(int orientation)
    215 {
    216     m_orientation = orientation;
    217     if (DOMWindow* window = domWindow())
    218         window->dispatchEvent(Event::create(EventTypeNames::orientationchange));
    219 }
    220 #endif // ENABLE(ORIENTATION_EVENTS)
    221 
    222 Settings* Frame::settings() const
    223 {
    224     return m_page ? &m_page->settings() : 0;
    225 }
    226 
    227 void Frame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio, AdjustViewSizeOrNot shouldAdjustViewSize)
    228 {
    229     // In setting printing, we should not validate resources already cached for the document.
    230     // See https://bugs.webkit.org/show_bug.cgi?id=43704
    231     ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher());
    232 
    233     document()->setPrinting(printing);
    234     view()->adjustMediaTypeForPrinting(printing);
    235 
    236     document()->styleResolverChanged(RecalcStyleImmediately);
    237     if (shouldUsePrintingLayout()) {
    238         view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio, shouldAdjustViewSize);
    239     } else {
    240         view()->forceLayout();
    241         if (shouldAdjustViewSize == AdjustViewSize)
    242             view()->adjustViewSize();
    243     }
    244 
    245     // Subframes of the one we're printing don't lay out to the page size.
    246     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
    247         child->setPrinting(printing, FloatSize(), FloatSize(), 0, shouldAdjustViewSize);
    248 }
    249 
    250 bool Frame::shouldUsePrintingLayout() const
    251 {
    252     // Only top frame being printed should be fit to page size.
    253     // Subframes should be constrained by parents only.
    254     return document()->printing() && (!tree().parent() || !tree().parent()->document()->printing());
    255 }
    256 
    257 FloatSize Frame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
    258 {
    259     FloatSize resultSize;
    260     if (!contentRenderer())
    261         return FloatSize();
    262 
    263     if (contentRenderer()->style()->isHorizontalWritingMode()) {
    264         ASSERT(fabs(originalSize.width()) > numeric_limits<float>::epsilon());
    265         float ratio = originalSize.height() / originalSize.width();
    266         resultSize.setWidth(floorf(expectedSize.width()));
    267         resultSize.setHeight(floorf(resultSize.width() * ratio));
    268     } else {
    269         ASSERT(fabs(originalSize.height()) > numeric_limits<float>::epsilon());
    270         float ratio = originalSize.width() / originalSize.height();
    271         resultSize.setHeight(floorf(expectedSize.height()));
    272         resultSize.setWidth(floorf(resultSize.height() * ratio));
    273     }
    274     return resultSize;
    275 }
    276 
    277 void Frame::setDOMWindow(PassRefPtr<DOMWindow> domWindow)
    278 {
    279     m_domWindow = domWindow;
    280 }
    281 
    282 static ChromeClient& emptyChromeClient()
    283 {
    284     DEFINE_STATIC_LOCAL(EmptyChromeClient, client, ());
    285     return client;
    286 }
    287 
    288 ChromeClient& Frame::chromeClient() const
    289 {
    290     if (Page* page = this->page())
    291         return page->chrome().client();
    292     return emptyChromeClient();
    293 }
    294 
    295 Document* Frame::document() const
    296 {
    297     return m_domWindow ? m_domWindow->document() : 0;
    298 }
    299 
    300 RenderView* Frame::contentRenderer() const
    301 {
    302     return document() ? document()->renderView() : 0;
    303 }
    304 
    305 RenderPart* Frame::ownerRenderer() const
    306 {
    307     if (!ownerElement())
    308         return 0;
    309     RenderObject* object = ownerElement()->renderer();
    310     if (!object)
    311         return 0;
    312     // FIXME: If <object> is ever fixed to disassociate itself from frames
    313     // that it has started but canceled, then this can turn into an ASSERT
    314     // since ownerElement() would be 0 when the load is canceled.
    315     // https://bugs.webkit.org/show_bug.cgi?id=18585
    316     if (!object->isRenderPart())
    317         return 0;
    318     return toRenderPart(object);
    319 }
    320 
    321 void Frame::dispatchVisibilityStateChangeEvent()
    322 {
    323     if (document())
    324         document()->dispatchVisibilityStateChangeEvent();
    325 
    326     Vector<RefPtr<Frame> > childFrames;
    327     for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling())
    328         childFrames.append(child);
    329 
    330     for (size_t i = 0; i < childFrames.size(); ++i)
    331         childFrames[i]->dispatchVisibilityStateChangeEvent();
    332 }
    333 
    334 void Frame::willDetachPage()
    335 {
    336     // We should never be detatching the page during a Layout.
    337     RELEASE_ASSERT(!m_view || !m_view->isInLayout());
    338 
    339     if (Frame* parent = tree().parent())
    340         parent->loader().checkLoadComplete();
    341 
    342     HashSet<FrameDestructionObserver*>::iterator stop = m_destructionObservers.end();
    343     for (HashSet<FrameDestructionObserver*>::iterator it = m_destructionObservers.begin(); it != stop; ++it)
    344         (*it)->willDetachPage();
    345 
    346     // FIXME: It's unclear as to why this is called more than once, but it is,
    347     // so page() could be NULL.
    348     if (page() && page()->focusController().focusedFrame() == this)
    349         page()->focusController().setFocusedFrame(0);
    350 
    351     if (page() && page()->scrollingCoordinator() && m_view)
    352         page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
    353 
    354     script().clearScriptObjects();
    355 }
    356 
    357 void Frame::detachFromPage()
    358 {
    359     // We should never be detatching the page during a Layout.
    360     RELEASE_ASSERT(!m_view || !m_view->isInLayout());
    361     m_page = 0;
    362 }
    363 
    364 void Frame::disconnectOwnerElement()
    365 {
    366     if (ownerElement()) {
    367         if (Document* doc = document())
    368             doc->topDocument()->clearAXObjectCache();
    369         ownerElement()->clearContentFrame();
    370         if (m_page)
    371             m_page->decrementSubframeCount();
    372     }
    373     m_frameInit->setOwnerElement(0);
    374 }
    375 
    376 bool Frame::isMainFrame() const
    377 {
    378     return m_page && this == m_page->mainFrame();
    379 }
    380 
    381 String Frame::documentTypeString() const
    382 {
    383     if (DocumentType* doctype = document()->doctype())
    384         return createMarkup(doctype);
    385 
    386     return String();
    387 }
    388 
    389 String Frame::selectedText() const
    390 {
    391     return selection().selectedText();
    392 }
    393 
    394 String Frame::selectedTextForClipboard() const
    395 {
    396     return selection().selectedTextForClipboard();
    397 }
    398 
    399 VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint)
    400 {
    401     HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint);
    402     Node* node = result.innerNonSharedNode();
    403     if (!node)
    404         return VisiblePosition();
    405     RenderObject* renderer = node->renderer();
    406     if (!renderer)
    407         return VisiblePosition();
    408     VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint()));
    409     if (visiblePos.isNull())
    410         visiblePos = firstPositionInOrBeforeNode(node);
    411     return visiblePos;
    412 }
    413 
    414 Document* Frame::documentAtPoint(const IntPoint& point)
    415 {
    416     if (!view())
    417         return 0;
    418 
    419     IntPoint pt = view()->windowToContents(point);
    420     HitTestResult result = HitTestResult(pt);
    421 
    422     if (contentRenderer())
    423         result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
    424     return result.innerNode() ? &result.innerNode()->document() : 0;
    425 }
    426 
    427 PassRefPtr<Range> Frame::rangeForPoint(const IntPoint& framePoint)
    428 {
    429     VisiblePosition position = visiblePositionForPoint(framePoint);
    430     if (position.isNull())
    431         return 0;
    432 
    433     VisiblePosition previous = position.previous();
    434     if (previous.isNotNull()) {
    435         RefPtr<Range> previousCharacterRange = makeRange(previous, position);
    436         LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
    437         if (rect.contains(framePoint))
    438             return previousCharacterRange.release();
    439     }
    440 
    441     VisiblePosition next = position.next();
    442     if (RefPtr<Range> nextCharacterRange = makeRange(position, next)) {
    443         LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
    444         if (rect.contains(framePoint))
    445             return nextCharacterRange.release();
    446     }
    447 
    448     return 0;
    449 }
    450 
    451 void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
    452     ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
    453     ScrollbarMode verticalScrollbarMode, bool verticalLock)
    454 {
    455     ASSERT(this);
    456     ASSERT(m_page);
    457 
    458     bool isMainFrame = this->isMainFrame();
    459 
    460     if (isMainFrame && view())
    461         view()->setParentVisible(false);
    462 
    463     setView(0);
    464 
    465     RefPtr<FrameView> frameView;
    466     if (isMainFrame) {
    467         frameView = FrameView::create(this, viewportSize);
    468 
    469         // The layout size is set by WebViewImpl to support @viewport
    470         frameView->setLayoutSizeFixedToFrameSize(false);
    471     } else
    472         frameView = FrameView::create(this);
    473 
    474     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
    475 
    476     setView(frameView);
    477 
    478     if (backgroundColor.isValid())
    479         frameView->updateBackgroundRecursively(backgroundColor, transparent);
    480 
    481     if (isMainFrame)
    482         frameView->setParentVisible(true);
    483 
    484     if (ownerRenderer())
    485         ownerRenderer()->setWidget(frameView);
    486 
    487     if (HTMLFrameOwnerElement* owner = ownerElement())
    488         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
    489 }
    490 
    491 String Frame::layerTreeAsText(unsigned flags) const
    492 {
    493     document()->updateLayout();
    494 
    495     if (!contentRenderer())
    496         return String();
    497 
    498     return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags));
    499 }
    500 
    501 String Frame::trackedRepaintRectsAsText() const
    502 {
    503     if (!m_view)
    504         return String();
    505     return m_view->trackedRepaintRectsAsText();
    506 }
    507 
    508 void Frame::setPageZoomFactor(float factor)
    509 {
    510     setPageAndTextZoomFactors(factor, m_textZoomFactor);
    511 }
    512 
    513 void Frame::setTextZoomFactor(float factor)
    514 {
    515     setPageAndTextZoomFactors(m_pageZoomFactor, factor);
    516 }
    517 
    518 void Frame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
    519 {
    520     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
    521         return;
    522 
    523     Page* page = this->page();
    524     if (!page)
    525         return;
    526 
    527     Document* document = this->document();
    528     if (!document)
    529         return;
    530 
    531     // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
    532     // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
    533     if (document->isSVGDocument()) {
    534         if (!toSVGDocument(document)->zoomAndPanEnabled())
    535             return;
    536     }
    537 
    538     if (m_pageZoomFactor != pageZoomFactor) {
    539         if (FrameView* view = this->view()) {
    540             // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
    541             LayoutPoint scrollPosition = view->scrollPosition();
    542             float percentDifference = (pageZoomFactor / m_pageZoomFactor);
    543             view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
    544         }
    545     }
    546 
    547     m_pageZoomFactor = pageZoomFactor;
    548     m_textZoomFactor = textZoomFactor;
    549 
    550     document->recalcStyle(Force);
    551 
    552     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
    553         child->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
    554 
    555     if (FrameView* view = this->view()) {
    556         if (document->renderer() && document->renderer()->needsLayout() && view->didFirstLayout())
    557             view->layout();
    558     }
    559 }
    560 
    561 void Frame::deviceOrPageScaleFactorChanged()
    562 {
    563     document()->mediaQueryAffectingValueChanged();
    564     for (RefPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling())
    565         child->deviceOrPageScaleFactorChanged();
    566 }
    567 
    568 void Frame::notifyChromeClientWheelEventHandlerCountChanged() const
    569 {
    570     // Ensure that this method is being called on the main frame of the page.
    571     ASSERT(isMainFrame());
    572 
    573     unsigned count = 0;
    574     for (const Frame* frame = this; frame; frame = frame->tree().traverseNext()) {
    575         if (frame->document())
    576             count += WheelController::from(frame->document())->wheelEventHandlerCount();
    577     }
    578 
    579     m_page->chrome().client().numWheelEventHandlersChanged(count);
    580 }
    581 
    582 bool Frame::isURLAllowed(const KURL& url) const
    583 {
    584     // We allow one level of self-reference because some sites depend on that,
    585     // but we don't allow more than one.
    586     if (m_page->subframeCount() >= Page::maxNumberOfFrames)
    587         return false;
    588     bool foundSelfReference = false;
    589     for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
    590         if (equalIgnoringFragmentIdentifier(frame->document()->url(), url)) {
    591             if (foundSelfReference)
    592                 return false;
    593             foundSelfReference = true;
    594         }
    595     }
    596     return true;
    597 }
    598 
    599 struct ScopedFramePaintingState {
    600     ScopedFramePaintingState(Frame* frame, Node* node)
    601         : frame(frame)
    602         , node(node)
    603         , paintBehavior(frame->view()->paintBehavior())
    604         , backgroundColor(frame->view()->baseBackgroundColor())
    605     {
    606         ASSERT(!node || node->renderer());
    607         if (node)
    608             node->renderer()->updateDragState(true);
    609     }
    610 
    611     ~ScopedFramePaintingState()
    612     {
    613         if (node && node->renderer())
    614             node->renderer()->updateDragState(false);
    615         frame->view()->setPaintBehavior(paintBehavior);
    616         frame->view()->setBaseBackgroundColor(backgroundColor);
    617         frame->view()->setNodeToDraw(0);
    618     }
    619 
    620     Frame* frame;
    621     Node* node;
    622     PaintBehavior paintBehavior;
    623     Color backgroundColor;
    624 };
    625 
    626 PassOwnPtr<DragImage> Frame::nodeImage(Node* node)
    627 {
    628     if (!node->renderer())
    629         return nullptr;
    630 
    631     const ScopedFramePaintingState state(this, node);
    632 
    633     m_view->setPaintBehavior(state.paintBehavior | PaintBehaviorFlattenCompositingLayers);
    634 
    635     // When generating the drag image for an element, ignore the document background.
    636     m_view->setBaseBackgroundColor(Color::transparent);
    637     document()->updateLayout();
    638     m_view->setNodeToDraw(node); // Enable special sub-tree drawing mode.
    639 
    640     // Document::updateLayout may have blown away the original RenderObject.
    641     RenderObject* renderer = node->renderer();
    642     if (!renderer)
    643         return nullptr;
    644 
    645     LayoutRect topLevelRect;
    646     IntRect paintingRect = pixelSnappedIntRect(renderer->paintingRootRect(topLevelRect));
    647 
    648     float deviceScaleFactor = 1;
    649     if (m_page)
    650         deviceScaleFactor = m_page->deviceScaleFactor();
    651     paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
    652     paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
    653 
    654     OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size());
    655     if (!buffer)
    656         return nullptr;
    657     buffer->context()->scale(FloatSize(deviceScaleFactor, deviceScaleFactor));
    658     buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
    659     buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
    660 
    661     m_view->paintContents(buffer->context(), paintingRect);
    662 
    663     RefPtr<Image> image = buffer->copyImage();
    664     return DragImage::create(image.get(), renderer->shouldRespectImageOrientation(), deviceScaleFactor);
    665 }
    666 
    667 PassOwnPtr<DragImage> Frame::dragImageForSelection()
    668 {
    669     if (!selection().isRange())
    670         return nullptr;
    671 
    672     const ScopedFramePaintingState state(this, 0);
    673     m_view->setPaintBehavior(PaintBehaviorSelectionOnly | PaintBehaviorFlattenCompositingLayers);
    674     document()->updateLayout();
    675 
    676     IntRect paintingRect = enclosingIntRect(selection().bounds());
    677 
    678     float deviceScaleFactor = 1;
    679     if (m_page)
    680         deviceScaleFactor = m_page->deviceScaleFactor();
    681     paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
    682     paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
    683 
    684     OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size());
    685     if (!buffer)
    686         return nullptr;
    687     buffer->context()->scale(FloatSize(deviceScaleFactor, deviceScaleFactor));
    688     buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
    689     buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
    690 
    691     m_view->paintContents(buffer->context(), paintingRect);
    692 
    693     RefPtr<Image> image = buffer->copyImage();
    694     return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor);
    695 }
    696 
    697 double Frame::devicePixelRatio() const
    698 {
    699     if (!m_page)
    700         return 0;
    701 
    702     double ratio = m_page->deviceScaleFactor();
    703     if (RuntimeEnabledFeatures::devicePixelRatioIncludesZoomEnabled())
    704         ratio *= pageZoomFactor();
    705     return ratio;
    706 }
    707 
    708 } // namespace WebCore
    709