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