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