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