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