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