Update To 11.40.268.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/html/HTMLPlugInElement.h"
52 #include "core/inspector/ConsoleMessageStorage.h"
53 #include "core/inspector/InspectorInstrumentation.h"
54 #include "core/loader/FrameLoaderClient.h"
55 #include "core/page/Chrome.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/RenderView.h"
63 #include "core/rendering/compositing/RenderLayerCompositor.h"
64 #include "core/svg/SVGDocumentExtensions.h"
65 #include "platform/DragImage.h"
66 #include "platform/RuntimeEnabledFeatures.h"
67 #include "platform/graphics/GraphicsContext.h"
68 #include "platform/graphics/ImageBuffer.h"
69 #include "platform/text/TextStream.h"
70 #include "wtf/PassOwnPtr.h"
71 #include "wtf/StdLibExtras.h"
72
73 namespace blink {
74
75 using namespace HTMLNames;
76
77 namespace {
78
79 struct ScopedFramePaintingState {
80     ScopedFramePaintingState(LocalFrame* frame, Node* node)
81         : frame(frame)
82         , node(node)
83         , paintBehavior(frame->view()->paintBehavior())
84     {
85         ASSERT(!node || node->renderer());
86         if (node)
87             node->renderer()->updateDragState(true);
88     }
89
90     ~ScopedFramePaintingState()
91     {
92         if (node && node->renderer())
93             node->renderer()->updateDragState(false);
94         frame->view()->setPaintBehavior(paintBehavior);
95         frame->view()->setNodeToDraw(0);
96     }
97
98     LocalFrame* frame;
99     Node* node;
100     PaintBehavior paintBehavior;
101 };
102
103 inline float parentPageZoomFactor(LocalFrame* frame)
104 {
105     Frame* parent = frame->tree().parent();
106     if (!parent || !parent->isLocalFrame())
107         return 1;
108     return toLocalFrame(parent)->pageZoomFactor();
109 }
110
111 inline float parentTextZoomFactor(LocalFrame* frame)
112 {
113     Frame* parent = frame->tree().parent();
114     if (!parent || !parent->isLocalFrame())
115         return 1;
116     return toLocalFrame(parent)->textZoomFactor();
117 }
118
119 } // namespace
120
121 PassRefPtrWillBeRawPtr<LocalFrame> LocalFrame::create(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
122 {
123     RefPtrWillBeRawPtr<LocalFrame> frame = adoptRefWillBeNoop(new LocalFrame(client, host, owner));
124     InspectorInstrumentation::frameAttachedToParent(frame.get());
125     return frame.release();
126 }
127
128 void LocalFrame::setView(PassRefPtrWillBeRawPtr<FrameView> view)
129 {
130     ASSERT(!m_view || m_view != view);
131     detachView();
132
133     // Prepare for destruction now, so any unload event handlers get run and the LocalDOMWindow is
134     // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
135     // these calls to work.
136     if (!view && document() && document()->isActive()) {
137         // FIXME: We don't call willRemove here. Why is that OK?
138         document()->prepareForDestruction();
139     }
140
141     eventHandler().clear();
142
143     m_view = view;
144
145     if (m_view && isMainFrame() && !settings()->pinchVirtualViewportEnabled())
146         m_view->setVisibleContentScaleFactor(page()->pageScaleFactor());
147 }
148
149 void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
150     ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
151     ScrollbarMode verticalScrollbarMode, bool verticalLock)
152 {
153     ASSERT(this);
154     ASSERT(page());
155
156     bool isLocalRoot = this->isLocalRoot();
157
158     if (isLocalRoot && view())
159         view()->setParentVisible(false);
160
161     setView(nullptr);
162
163     RefPtrWillBeRawPtr<FrameView> frameView = nullptr;
164     if (isLocalRoot) {
165         frameView = FrameView::create(this, viewportSize);
166
167         // The layout size is set by WebViewImpl to support @viewport
168         frameView->setLayoutSizeFixedToFrameSize(false);
169     } else {
170         frameView = FrameView::create(this);
171     }
172
173     frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
174
175     setView(frameView);
176
177     frameView->updateBackgroundRecursively(backgroundColor, transparent);
178
179     if (isLocalRoot)
180         frameView->setParentVisible(true);
181
182     // FIXME: Not clear what the right thing for OOPI is here.
183     if (ownerRenderer()) {
184         HTMLFrameOwnerElement* owner = deprecatedLocalOwner();
185         ASSERT(owner);
186         // FIXME: OOPI might lead to us temporarily lying to a frame and telling it
187         // that it's owned by a FrameOwner that knows nothing about it. If we're
188         // lying to this frame, don't let it clobber the existing widget.
189         if (owner->contentFrame() == this)
190             owner->setWidget(frameView);
191     }
192
193     if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner())
194         view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
195 }
196
197 LocalFrame::~LocalFrame()
198 {
199 #if ENABLE(OILPAN)
200     // Verify that the FrameView has been cleared as part of detaching
201     // the frame owner.
202     ASSERT(!m_view);
203     // Oilpan: see setDOMWindow() comment why it is acceptable not to
204     // mirror the non-Oilpan call below.
205     //
206     // Also, FrameDestructionObservers that live longer than this
207     // frame object keep weak references to the frame; those will be
208     // automatically cleared by the garbage collector. Hence, explicit
209     // frameDestroyed() notifications aren't needed.
210 #else
211     // FIXME: follow Oilpan and clear the FrameView and FrameLoader
212     // during FrameOwner detachment instead, see LocalFrame::disconnectOwnerElement().
213     setView(nullptr);
214     m_loader.clear();
215     setDOMWindow(nullptr);
216
217     for (const auto& frameDestructionObserver : m_destructionObservers)
218         frameDestructionObserver->frameDestroyed();
219 #endif
220 }
221
222 void LocalFrame::trace(Visitor* visitor)
223 {
224 #if ENABLE(OILPAN)
225     visitor->trace(m_destructionObservers);
226     visitor->trace(m_loader);
227     visitor->trace(m_navigationScheduler);
228     visitor->trace(m_view);
229     visitor->trace(m_domWindow);
230     visitor->trace(m_pagePopupOwner);
231     visitor->trace(m_script);
232     visitor->trace(m_editor);
233     visitor->trace(m_spellChecker);
234     visitor->trace(m_selection);
235     visitor->trace(m_eventHandler);
236     visitor->trace(m_console);
237     visitor->trace(m_inputMethodController);
238     visitor->registerWeakMembers<LocalFrame, &LocalFrame::clearWeakMembers>(this);
239     HeapSupplementable<LocalFrame>::trace(visitor);
240 #endif
241     Frame::trace(visitor);
242 }
243
244 LocalDOMWindow* LocalFrame::domWindow() const
245 {
246     return m_domWindow.get();
247 }
248
249 void LocalFrame::navigate(Document& originDocument, const KURL& url, bool lockBackForwardList)
250 {
251     m_navigationScheduler.scheduleLocationChange(&originDocument, url.string(), lockBackForwardList);
252 }
253
254 void LocalFrame::detach()
255 {
256     // A lot of the following steps can result in the current frame being
257     // detached, so protect a reference to it.
258     RefPtrWillBeRawPtr<LocalFrame> protect(this);
259     m_loader.stopAllLoaders();
260     m_loader.closeURL();
261     detachChildren();
262     // stopAllLoaders() needs to be called after detachChildren(), because detachChildren()
263     // will trigger the unload event handlers of any child frames, and those event
264     // handlers might start a new subresource load in this frame.
265     m_loader.stopAllLoaders();
266     if (!client())
267         return;
268     m_loader.detach();
269     setView(nullptr);
270     willDetachFrameHost();
271     // Notify ScriptController that the frame is closing, since its cleanup ends up calling
272     // back to FrameLoaderClient via WindowProxy.
273     script().clearForClose();
274     InspectorInstrumentation::frameDetachedFromParent(this);
275     Frame::detach();
276 #if ENABLE(OILPAN)
277     // Clear the FrameLoader right here rather than during
278     // finalization. Too late to access various heap objects at that
279     // stage.
280     loader().clear();
281 #endif
282 }
283
284 void LocalFrame::disconnectOwnerElement()
285 {
286     if (owner()) {
287         if (Document* document = this->document())
288             document->topDocument().clearAXObjectCache();
289 #if ENABLE(OILPAN)
290         // First give the plugin elements holding persisted,
291         // renderer-less plugins the opportunity to dispose of them.
292         for (const auto& pluginElement : m_pluginElements)
293             pluginElement->disconnectContentFrame();
294         m_pluginElements.clear();
295 #endif
296     }
297     Frame::disconnectOwnerElement();
298 }
299
300 void LocalFrame::addDestructionObserver(FrameDestructionObserver* observer)
301 {
302     m_destructionObservers.add(observer);
303 }
304
305 void LocalFrame::removeDestructionObserver(FrameDestructionObserver* observer)
306 {
307     m_destructionObservers.remove(observer);
308 }
309
310 void LocalFrame::willDetachFrameHost()
311 {
312
313     for (const auto& frameDestructionObserver : m_destructionObservers)
314         frameDestructionObserver->willDetachFrameHost();
315
316     // FIXME: Page should take care of updating focus/scrolling instead of Frame.
317     // FIXME: It's unclear as to why this is called more than once, but it is,
318     // so page() could be null.
319     if (page() && page()->focusController().focusedFrame() == this)
320         page()->focusController().setFocusedFrame(nullptr);
321     script().clearScriptObjects();
322
323     if (page() && page()->scrollingCoordinator() && m_view)
324         page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
325 }
326
327 void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)
328 {
329     // Oilpan: setDOMWindow() cannot be used when finalizing. Which
330     // is acceptable as its actions are either not needed or handled
331     // by other means --
332     //
333     //  - FrameDestructionObserver::willDetachFrameHost() will have
334     //    signalled the Inspector frameWindowDiscarded() notifications.
335     //    We assume that all LocalFrames are detached, where that notification
336     //    will have been done.
337     //
338     //  - Calling LocalDOMWindow::reset() is not needed (called from
339     //    Frame::setDOMWindow().) The Member references it clears will now
340     //    die with the window. And the registered DOMWindowProperty instances that don't,
341     //    only keep a weak reference to this frame, so there's no need to be
342     //    explicitly notified that this frame is going away.
343     if (m_domWindow && host()) {
344         host()->consoleMessageStorage().frameWindowDiscarded(m_domWindow.get());
345         InspectorInstrumentation::frameWindowDiscarded(this, m_domWindow.get());
346     }
347     if (domWindow)
348         script().clearWindowProxy();
349
350     if (m_domWindow)
351         m_domWindow->reset();
352     m_domWindow = domWindow;
353 }
354
355 Document* LocalFrame::document() const
356 {
357     return m_domWindow ? m_domWindow->document() : 0;
358 }
359
360 void LocalFrame::setPagePopupOwner(Element& owner)
361 {
362     m_pagePopupOwner = &owner;
363 }
364
365 RenderView* LocalFrame::contentRenderer() const
366 {
367     return document() ? document()->renderView() : 0;
368 }
369
370 void LocalFrame::didChangeVisibilityState()
371 {
372     if (document())
373         document()->didChangeVisibilityState();
374
375     WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > childFrames;
376     for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) {
377         if (child->isLocalFrame())
378             childFrames.append(toLocalFrame(child));
379     }
380
381     for (size_t i = 0; i < childFrames.size(); ++i)
382         childFrames[i]->didChangeVisibilityState();
383 }
384
385 LocalFrame* LocalFrame::localFrameRoot()
386 {
387     LocalFrame* curFrame = this;
388     while (curFrame && curFrame->tree().parent() && curFrame->tree().parent()->isLocalFrame())
389         curFrame = toLocalFrame(curFrame->tree().parent());
390
391     return curFrame;
392 }
393
394 bool LocalFrame::inScope(TreeScope* scope) const
395 {
396     ASSERT(scope);
397     Document* doc = document();
398     if (!doc)
399         return false;
400     // FIXME: This check is broken in for OOPI.
401     HTMLFrameOwnerElement* owner = doc->ownerElement();
402     if (!owner)
403         return false;
404     return owner->treeScope() == scope;
405 }
406
407 void LocalFrame::countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial)
408 {
409     RenderObject* root = view()->layoutRoot();
410     isPartial = true;
411     if (!root) {
412         isPartial = false;
413         root = contentRenderer();
414     }
415
416     needsLayoutObjects = 0;
417     totalObjects = 0;
418
419     for (RenderObject* o = root; o; o = o->nextInPreOrder(root)) {
420         ++totalObjects;
421         if (o->needsLayout())
422             ++needsLayoutObjects;
423     }
424 }
425
426 String LocalFrame::layerTreeAsText(LayerTreeFlags flags) const
427 {
428     TextStream textStream;
429     textStream << localLayerTreeAsText(flags);
430
431     for (Frame* child = tree().firstChild(); child; child = child->tree().traverseNext(this)) {
432         if (!child->isLocalFrame())
433             continue;
434         String childLayerTree = toLocalFrame(child)->localLayerTreeAsText(flags);
435         if (!childLayerTree.length())
436             continue;
437
438         textStream << "\n\n--------\nFrame: '";
439         textStream << child->tree().uniqueName();
440         textStream << "'\n--------\n";
441         textStream << childLayerTree;
442     }
443
444     return textStream.release();
445 }
446
447 void LocalFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio)
448 {
449     // In setting printing, we should not validate resources already cached for the document.
450     // See https://bugs.webkit.org/show_bug.cgi?id=43704
451     ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher());
452
453     document()->setPrinting(printing);
454     view()->adjustMediaTypeForPrinting(printing);
455
456     document()->styleResolverChanged();
457     if (shouldUsePrintingLayout()) {
458         view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio);
459     } else {
460         view()->forceLayout();
461         view()->adjustViewSize();
462     }
463
464     // Subframes of the one we're printing don't lay out to the page size.
465     for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
466         if (child->isLocalFrame())
467             toLocalFrame(child.get())->setPrinting(printing, FloatSize(), FloatSize(), 0);
468     }
469 }
470
471 bool LocalFrame::shouldUsePrintingLayout() const
472 {
473     // Only top frame being printed should be fit to page size.
474     // Subframes should be constrained by parents only.
475     return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing());
476 }
477
478 FloatSize LocalFrame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
479 {
480     FloatSize resultSize;
481     if (!contentRenderer())
482         return FloatSize();
483
484     if (contentRenderer()->style()->isHorizontalWritingMode()) {
485         ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
486         float ratio = originalSize.height() / originalSize.width();
487         resultSize.setWidth(floorf(expectedSize.width()));
488         resultSize.setHeight(floorf(resultSize.width() * ratio));
489     } else {
490         ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
491         float ratio = originalSize.width() / originalSize.height();
492         resultSize.setHeight(floorf(expectedSize.height()));
493         resultSize.setWidth(floorf(resultSize.height() * ratio));
494     }
495     return resultSize;
496 }
497
498 void LocalFrame::setPageZoomFactor(float factor)
499 {
500     setPageAndTextZoomFactors(factor, m_textZoomFactor);
501 }
502
503 void LocalFrame::setTextZoomFactor(float factor)
504 {
505     setPageAndTextZoomFactors(m_pageZoomFactor, factor);
506 }
507
508 void LocalFrame::setPageAndTextZoomFactors(float pageZoomFactor, float textZoomFactor)
509 {
510     if (m_pageZoomFactor == pageZoomFactor && m_textZoomFactor == textZoomFactor)
511         return;
512
513     Page* page = this->page();
514     if (!page)
515         return;
516
517     Document* document = this->document();
518     if (!document)
519         return;
520
521     // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
522     // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
523     if (document->isSVGDocument()) {
524         if (!document->accessSVGExtensions().zoomAndPanEnabled())
525             return;
526     }
527
528     if (m_pageZoomFactor != pageZoomFactor) {
529         if (FrameView* view = this->view()) {
530             // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
531             LayoutPoint scrollPosition = view->scrollPosition();
532             float percentDifference = (pageZoomFactor / m_pageZoomFactor);
533             view->setScrollPosition(DoublePoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
534         }
535     }
536
537     m_pageZoomFactor = pageZoomFactor;
538     m_textZoomFactor = textZoomFactor;
539
540     for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
541         if (child->isLocalFrame())
542             toLocalFrame(child.get())->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
543     }
544
545     document->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Zoom));
546     document->updateLayoutIgnorePendingStylesheets();
547 }
548
549 void LocalFrame::deviceOrPageScaleFactorChanged()
550 {
551     document()->mediaQueryAffectingValueChanged();
552     for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
553         if (child->isLocalFrame())
554             toLocalFrame(child.get())->deviceOrPageScaleFactorChanged();
555     }
556 }
557
558 double LocalFrame::devicePixelRatio() const
559 {
560     if (!m_host)
561         return 0;
562
563     double ratio = m_host->deviceScaleFactor();
564     ratio *= pageZoomFactor();
565     return ratio;
566 }
567
568 String LocalFrame::documentTypeString() const
569 {
570     if (DocumentType* doctype = document()->doctype())
571         return createMarkup(doctype);
572
573     return String();
574 }
575
576 PassOwnPtr<DragImage> LocalFrame::nodeImage(Node& node)
577 {
578     if (!node.renderer())
579         return nullptr;
580
581     const ScopedFramePaintingState state(this, &node);
582
583     m_view->updateLayoutAndStyleForPainting();
584
585     m_view->setPaintBehavior(state.paintBehavior | PaintBehaviorFlattenCompositingLayers);
586
587     m_view->setNodeToDraw(&node); // Enable special sub-tree drawing mode.
588
589     // Document::updateLayout may have blown away the original RenderObject.
590     RenderObject* renderer = node.renderer();
591     if (!renderer)
592         return nullptr;
593
594     LayoutRect topLevelRect;
595     IntRect paintingRect = pixelSnappedIntRect(renderer->paintingRootRect(topLevelRect));
596
597     ASSERT(document()->isActive());
598     float deviceScaleFactor = m_host->deviceScaleFactor();
599     paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
600     paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
601
602     OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size());
603     if (!buffer)
604         return nullptr;
605     buffer->context()->scale(deviceScaleFactor, deviceScaleFactor);
606     buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
607     buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
608
609     m_view->paintContents(buffer->context(), paintingRect);
610
611     RefPtr<Image> image = buffer->copyImage();
612     return DragImage::create(image.get(), renderer->shouldRespectImageOrientation(), deviceScaleFactor);
613 }
614
615 PassOwnPtr<DragImage> LocalFrame::dragImageForSelection()
616 {
617     if (!selection().isRange())
618         return nullptr;
619
620     const ScopedFramePaintingState state(this, 0);
621     m_view->setPaintBehavior(PaintBehaviorSelectionOnly | PaintBehaviorFlattenCompositingLayers);
622     m_view->updateLayoutAndStyleForPainting();
623
624     IntRect paintingRect = enclosingIntRect(selection().bounds());
625
626     ASSERT(document()->isActive());
627     float deviceScaleFactor = m_host->deviceScaleFactor();
628     paintingRect.setWidth(paintingRect.width() * deviceScaleFactor);
629     paintingRect.setHeight(paintingRect.height() * deviceScaleFactor);
630
631     OwnPtr<ImageBuffer> buffer = ImageBuffer::create(paintingRect.size());
632     if (!buffer)
633         return nullptr;
634     buffer->context()->scale(deviceScaleFactor, deviceScaleFactor);
635     buffer->context()->translate(-paintingRect.x(), -paintingRect.y());
636     buffer->context()->clip(FloatRect(0, 0, paintingRect.maxX(), paintingRect.maxY()));
637
638     m_view->paintContents(buffer->context(), paintingRect);
639
640     RefPtr<Image> image = buffer->copyImage();
641     return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor);
642 }
643
644 String LocalFrame::selectedText() const
645 {
646     return selection().selectedText();
647 }
648
649 String LocalFrame::selectedTextForClipboard() const
650 {
651     return selection().selectedTextForClipboard();
652 }
653
654 VisiblePosition LocalFrame::visiblePositionForPoint(const IntPoint& framePoint)
655 {
656     HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint);
657     Node* node = result.innerNonSharedNode();
658     if (!node)
659         return VisiblePosition();
660     RenderObject* renderer = node->renderer();
661     if (!renderer)
662         return VisiblePosition();
663     VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint()));
664     if (visiblePos.isNull())
665         visiblePos = VisiblePosition(firstPositionInOrBeforeNode(node));
666     return visiblePos;
667 }
668
669 Document* LocalFrame::documentAtPoint(const IntPoint& point)
670 {
671     if (!view())
672         return 0;
673
674     IntPoint pt = view()->windowToContents(point);
675     HitTestResult result = HitTestResult(pt);
676
677     if (contentRenderer())
678         result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active);
679     return result.innerNode() ? &result.innerNode()->document() : 0;
680 }
681
682 PassRefPtrWillBeRawPtr<Range> LocalFrame::rangeForPoint(const IntPoint& framePoint)
683 {
684     VisiblePosition position = visiblePositionForPoint(framePoint);
685     if (position.isNull())
686         return nullptr;
687
688     VisiblePosition previous = position.previous();
689     if (previous.isNotNull()) {
690         RefPtrWillBeRawPtr<Range> previousCharacterRange = makeRange(previous, position);
691         LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
692         if (rect.contains(framePoint))
693             return previousCharacterRange.release();
694     }
695
696     VisiblePosition next = position.next();
697     if (RefPtrWillBeRawPtr<Range> nextCharacterRange = makeRange(position, next)) {
698         LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
699         if (rect.contains(framePoint))
700             return nextCharacterRange.release();
701     }
702
703     return nullptr;
704 }
705
706 bool LocalFrame::isURLAllowed(const KURL& url) const
707 {
708     // We allow one level of self-reference because some sites depend on that,
709     // but we don't allow more than one.
710     if (host()->subframeCount() >= FrameHost::maxNumberOfFrames)
711         return false;
712     bool foundSelfReference = false;
713     for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
714         if (!frame->isLocalFrame())
715             continue;
716         if (equalIgnoringFragmentIdentifier(toLocalFrame(frame)->document()->url(), url)) {
717             if (foundSelfReference)
718                 return false;
719             foundSelfReference = true;
720         }
721     }
722     return true;
723 }
724
725 bool LocalFrame::shouldReuseDefaultView(const KURL& url) const
726 {
727     return loader().stateMachine()->isDisplayingInitialEmptyDocument() && document()->isSecureTransitionTo(url);
728 }
729
730 void LocalFrame::removeSpellingMarkersUnderWords(const Vector<String>& words)
731 {
732     spellChecker().removeSpellingMarkersUnderWords(words);
733 }
734
735 #if ENABLE(OILPAN)
736 void LocalFrame::registerPluginElement(HTMLPlugInElement* plugin)
737 {
738     m_pluginElements.add(plugin);
739 }
740
741 void LocalFrame::unregisterPluginElement(HTMLPlugInElement* plugin)
742 {
743     ASSERT(m_pluginElements.contains(plugin));
744     m_pluginElements.remove(plugin);
745 }
746
747 void LocalFrame::clearWeakMembers(Visitor* visitor)
748 {
749     Vector<HTMLPlugInElement*> deadPlugins;
750     for (const auto& pluginElement : m_pluginElements) {
751         if (!visitor->isAlive(pluginElement)) {
752             pluginElement->shouldDisposePlugin();
753             deadPlugins.append(pluginElement);
754         }
755     }
756     for (unsigned i = 0; i < deadPlugins.size(); ++i)
757         m_pluginElements.remove(deadPlugins[i]);
758 }
759 #endif
760
761 String LocalFrame::localLayerTreeAsText(unsigned flags) const
762 {
763     if (!contentRenderer())
764         return String();
765
766     return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags));
767 }
768
769 inline LocalFrame::LocalFrame(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
770     : Frame(client, host, owner)
771     , m_loader(this)
772     , m_navigationScheduler(this)
773     , m_script(ScriptController::create(this))
774     , m_editor(Editor::create(*this))
775     , m_spellChecker(SpellChecker::create(*this))
776     , m_selection(FrameSelection::create(this))
777     , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this)))
778     , m_console(FrameConsole::create(*this))
779     , m_inputMethodController(InputMethodController::create(*this))
780     , m_pageZoomFactor(parentPageZoomFactor(this))
781     , m_textZoomFactor(parentTextZoomFactor(this))
782     , m_inViewSourceMode(false)
783 {
784 }
785
786 void LocalFrame::detachView()
787 {
788     // We detach the FrameView's custom scroll bars as early as
789     // possible to prevent m_doc->detach() from messing with the view
790     // such that its scroll bars won't be torn down.
791     //
792     // FIXME: We should revisit this.
793     if (m_view)
794         m_view->prepareForDetach();
795 }
796
797 } // namespace blink