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