• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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 
parentPageZoomFactor(LocalFrame * frame)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 
parentTextZoomFactor(LocalFrame * frame)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 
LocalFrame(FrameLoaderClient * client,FrameHost * host,FrameOwner * owner)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 
create(FrameLoaderClient * client,FrameHost * host,FrameOwner * owner)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 
~LocalFrame()113 LocalFrame::~LocalFrame()
114 {
115     setView(nullptr);
116     loader().clear();
117     setDOMWindow(nullptr);
118 }
119 
inScope(TreeScope * scope) const120 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 
setView(PassRefPtr<FrameView> view)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 
sendOrientationChangeEvent()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 
setPrinting(bool printing,const FloatSize & pageSize,const FloatSize & originalPageSize,float maximumShrinkRatio)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 
shouldUsePrintingLayout() const209 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 
resizePageRectsKeepingRatio(const FloatSize & originalSize,const FloatSize & expectedSize)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 
setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)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 
didChangeVisibilityState()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 
willDetachFrameHost()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 
detachFromFrameHost()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 
documentTypeString() const282 String LocalFrame::documentTypeString() const
283 {
284     if (DocumentType* doctype = document()->doctype())
285         return createMarkup(doctype);
286 
287     return String();
288 }
289 
selectedText() const290 String LocalFrame::selectedText() const
291 {
292     return selection().selectedText();
293 }
294 
selectedTextForClipboard() const295 String LocalFrame::selectedTextForClipboard() const
296 {
297     return selection().selectedTextForClipboard();
298 }
299 
visiblePositionForPoint(const IntPoint & framePoint)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 
contentRenderer() const315 RenderView* LocalFrame::contentRenderer() const
316 {
317     return document() ? document()->renderView() : 0;
318 }
319 
document() const320 Document* LocalFrame::document() const
321 {
322     return m_domWindow ? m_domWindow->document() : 0;
323 }
324 
documentAtPoint(const IntPoint & point)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 
rangeForPoint(const IntPoint & framePoint)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 
createView(const IntSize & viewportSize,const Color & backgroundColor,bool transparent,ScrollbarMode horizontalScrollbarMode,bool horizontalLock,ScrollbarMode verticalScrollbarMode,bool verticalLock)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 
countObjectsNeedingLayout(unsigned & needsLayoutObjects,unsigned & totalObjects,bool & isPartial)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 
layerTreeAsText(LayerTreeFlags flags) const425 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 
localLayerTreeAsText(unsigned flags) const446 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 
trackedRepaintRectsAsText() const454 String LocalFrame::trackedRepaintRectsAsText() const
455 {
456     if (!m_view)
457         return String();
458     return m_view->trackedPaintInvalidationRectsAsText();
459 }
460 
setPageZoomFactor(float factor)461 void LocalFrame::setPageZoomFactor(float factor)
462 {
463     setPageAndTextZoomFactors(factor, m_textZoomFactor);
464 }
465 
setTextZoomFactor(float factor)466 void LocalFrame::setTextZoomFactor(float factor)
467 {
468     setPageAndTextZoomFactors(m_pageZoomFactor, factor);
469 }
470 
setPageAndTextZoomFactors(float pageZoomFactor,float textZoomFactor)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 
deviceOrPageScaleFactorChanged()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 
isURLAllowed(const KURL & url) const521 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 {
ScopedFramePaintingStateWebCore::ScopedFramePaintingState541     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 
~ScopedFramePaintingStateWebCore::ScopedFramePaintingState551     ~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 
nodeImage(Node & node)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 
dragImageForSelection()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 
devicePixelRatio() const632 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 
disconnectOwnerElement()642 void LocalFrame::disconnectOwnerElement()
643 {
644     if (owner()) {
645         if (Document* doc = document())
646             doc->topDocument().clearAXObjectCache();
647     }
648     Frame::disconnectOwnerElement();
649 }
650 
localFrameRoot()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