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.
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.
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.
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.
31 #include "core/frame/LocalFrame.h"
33 #include "bindings/core/v8/ScriptController.h"
34 #include "core/dom/DocumentType.h"
35 #include "core/editing/EditingUtilities.h"
36 #include "core/editing/Editor.h"
37 #include "core/editing/FrameSelection.h"
38 #include "core/editing/InputMethodController.h"
39 #include "core/editing/serializers/Serialization.h"
40 #include "core/editing/spellcheck/SpellChecker.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/FrameHost.h"
46 #include "core/frame/FrameView.h"
47 #include "core/frame/LocalDOMWindow.h"
48 #include "core/frame/Settings.h"
49 #include "core/html/HTMLFrameElementBase.h"
50 #include "core/html/HTMLPlugInElement.h"
51 #include "core/input/EventHandler.h"
52 #include "core/inspector/ConsoleMessageStorage.h"
53 #include "core/inspector/InspectorInstrumentation.h"
54 #include "core/inspector/InstrumentingAgents.h"
55 #include "core/layout/HitTestResult.h"
56 #include "core/layout/LayoutView.h"
57 #include "core/layout/compositing/DeprecatedPaintLayerCompositor.h"
58 #include "core/loader/FrameLoadRequest.h"
59 #include "core/loader/FrameLoaderClient.h"
60 #include "core/page/FocusController.h"
61 #include "core/page/Page.h"
62 #include "core/page/scrolling/ScrollingCoordinator.h"
63 #include "core/paint/DeprecatedPaintLayer.h"
64 #include "core/paint/TransformRecorder.h"
65 #include "core/svg/SVGDocumentExtensions.h"
66 #include "platform/DragImage.h"
67 #include "platform/PluginScriptForbiddenScope.h"
68 #include "platform/RuntimeEnabledFeatures.h"
69 #include "platform/ScriptForbiddenScope.h"
70 #include "platform/graphics/GraphicsContext.h"
71 #include "platform/graphics/StaticBitmapImage.h"
72 #include "platform/graphics/paint/ClipRecorder.h"
73 #include "platform/graphics/paint/SkPictureBuilder.h"
74 #include "platform/text/TextStream.h"
75 #include "third_party/skia/include/core/SkImage.h"
76 #include "wtf/PassOwnPtr.h"
77 #include "wtf/StdLibExtras.h"
81 using namespace HTMLNames
;
85 struct ScopedFramePaintingState
{
88 ScopedFramePaintingState(LocalFrame
* frame
, Node
* node
)
92 ASSERT(!node
|| node
->layoutObject());
94 node
->layoutObject()->updateDragState(true);
97 ~ScopedFramePaintingState()
99 if (node
&& node
->layoutObject())
100 node
->layoutObject()->updateDragState(false);
101 frame
->view()->setNodeToDraw(0);
104 RawPtrWillBeMember
<LocalFrame
> frame
;
105 RawPtrWillBeMember
<Node
> node
;
108 inline float parentPageZoomFactor(LocalFrame
* frame
)
110 Frame
* parent
= frame
->tree().parent();
111 if (!parent
|| !parent
->isLocalFrame())
113 return toLocalFrame(parent
)->pageZoomFactor();
116 inline float parentTextZoomFactor(LocalFrame
* frame
)
118 Frame
* parent
= frame
->tree().parent();
119 if (!parent
|| !parent
->isLocalFrame())
121 return toLocalFrame(parent
)->textZoomFactor();
126 PassRefPtrWillBeRawPtr
<LocalFrame
> LocalFrame::create(FrameLoaderClient
* client
, FrameHost
* host
, FrameOwner
* owner
)
128 RefPtrWillBeRawPtr
<LocalFrame
> frame
= adoptRefWillBeNoop(new LocalFrame(client
, host
, owner
));
129 InspectorInstrumentation::frameAttachedToParent(frame
.get());
130 return frame
.release();
133 void LocalFrame::setView(PassRefPtrWillBeRawPtr
<FrameView
> view
)
135 ASSERT(!m_view
|| m_view
!= view
);
136 ASSERT(!document() || !document()->isActive());
138 eventHandler().clear();
143 void LocalFrame::createView(const IntSize
& viewportSize
, const Color
& backgroundColor
, bool transparent
,
144 ScrollbarMode horizontalScrollbarMode
, bool horizontalLock
,
145 ScrollbarMode verticalScrollbarMode
, bool verticalLock
)
150 bool isLocalRoot
= this->isLocalRoot();
152 if (isLocalRoot
&& view())
153 view()->setParentVisible(false);
157 RefPtrWillBeRawPtr
<FrameView
> frameView
= nullptr;
159 frameView
= FrameView::create(this, viewportSize
);
161 // The layout size is set by WebViewImpl to support @viewport
162 frameView
->setLayoutSizeFixedToFrameSize(false);
164 frameView
= FrameView::create(this);
167 frameView
->setScrollbarModes(horizontalScrollbarMode
, verticalScrollbarMode
, horizontalLock
, verticalLock
);
171 frameView
->updateBackgroundRecursively(backgroundColor
, transparent
);
174 frameView
->setParentVisible(true);
176 // FIXME: Not clear what the right thing for OOPI is here.
177 if (ownerLayoutObject()) {
178 HTMLFrameOwnerElement
* owner
= deprecatedLocalOwner();
180 // FIXME: OOPI might lead to us temporarily lying to a frame and telling it
181 // that it's owned by a FrameOwner that knows nothing about it. If we're
182 // lying to this frame, don't let it clobber the existing widget.
183 if (owner
->contentFrame() == this)
184 owner
->setWidget(frameView
);
187 if (HTMLFrameOwnerElement
* owner
= deprecatedLocalOwner())
188 view()->setCanHaveScrollbars(owner
->scrollingMode() != ScrollbarAlwaysOff
);
191 LocalFrame::~LocalFrame()
193 // Verify that the FrameView has been cleared as part of detaching
197 // Oilpan: see setDOMWindow() comment why it is acceptable not to
198 // explicitly call setDOMWindow() here.
199 setDOMWindow(nullptr);
203 DEFINE_TRACE(LocalFrame
)
205 visitor
->trace(m_instrumentingAgents
);
207 visitor
->trace(m_loader
);
208 visitor
->trace(m_navigationScheduler
);
209 visitor
->trace(m_view
);
210 visitor
->trace(m_domWindow
);
211 visitor
->trace(m_pagePopupOwner
);
212 visitor
->trace(m_script
);
213 visitor
->trace(m_editor
);
214 visitor
->trace(m_spellChecker
);
215 visitor
->trace(m_selection
);
216 visitor
->trace(m_eventHandler
);
217 visitor
->trace(m_console
);
218 visitor
->trace(m_inputMethodController
);
219 visitor
->template registerWeakMembers
<LocalFrame
, &LocalFrame::clearWeakMembers
>(this);
220 HeapSupplementable
<LocalFrame
>::trace(visitor
);
222 LocalFrameLifecycleNotifier::trace(visitor
);
223 Frame::trace(visitor
);
226 DOMWindow
* LocalFrame::domWindow() const
228 return m_domWindow
.get();
231 WindowProxy
* LocalFrame::windowProxy(DOMWrapperWorld
& world
)
233 return m_script
->windowProxy(world
);
236 void LocalFrame::navigate(Document
& originDocument
, const KURL
& url
, bool replaceCurrentItem
, UserGestureStatus userGestureStatus
)
238 // TODO(dcheng): Special case for window.open("about:blank") to ensure it loads synchronously into
239 // a new window. This is our historical behavior, and it's consistent with the creation of
240 // a new iframe with src="about:blank". Perhaps we could get rid of this if we started reporting
241 // the initial empty document's url as about:blank? See crbug.com/471239.
242 // TODO(japhet): This special case is also necessary for behavior asserted by some extensions tests.
243 // Using NavigationScheduler::scheduleNavigationChange causes the navigation to be flagged as a
244 // client redirect, which is observable via the webNavigation extension api.
245 if (isMainFrame() && !m_loader
.stateMachine()->committedFirstRealDocumentLoad()) {
246 FrameLoadRequest
request(&originDocument
, url
);
247 request
.resourceRequest().setHasUserGesture(userGestureStatus
== UserGestureStatus::Active
);
248 m_loader
.load(request
);
250 m_navigationScheduler
.scheduleLocationChange(&originDocument
, url
.string(), replaceCurrentItem
);
254 void LocalFrame::navigate(const FrameLoadRequest
& request
)
256 m_loader
.load(request
);
259 void LocalFrame::reload(FrameLoadType loadType
, ClientRedirectPolicy clientRedirectPolicy
)
261 ASSERT(loadType
== FrameLoadTypeReload
|| loadType
== FrameLoadTypeReloadFromOrigin
);
262 ASSERT(clientRedirectPolicy
== NotClientRedirect
|| loadType
== FrameLoadTypeReload
);
263 if (clientRedirectPolicy
== NotClientRedirect
) {
264 if (!m_loader
.currentItem())
266 FrameLoadRequest request
= FrameLoadRequest(
267 nullptr, m_loader
.resourceRequestForReload(loadType
, KURL(), clientRedirectPolicy
));
268 request
.setClientRedirect(clientRedirectPolicy
);
269 m_loader
.load(request
, loadType
);
271 m_navigationScheduler
.scheduleReload();
275 void LocalFrame::detach(FrameDetachType type
)
277 PluginScriptForbiddenScope forbidPluginDestructorScripting
;
278 // A lot of the following steps can result in the current frame being
279 // detached, so protect a reference to it.
280 RefPtrWillBeRawPtr
<LocalFrame
> protect(this);
281 m_loader
.stopAllLoaders();
282 m_loader
.dispatchUnloadEvent();
285 // All done if detaching the subframes brought about a detach of this frame also.
289 // stopAllLoaders() needs to be called after detachChildren(), because detachChildren()
290 // will trigger the unload event handlers of any child frames, and those event
291 // handlers might start a new subresource load in this frame.
292 m_loader
.stopAllLoaders();
294 document()->detach();
299 client()->willBeDetached();
300 // Notify ScriptController that the frame is closing, since its cleanup ends up calling
301 // back to FrameLoaderClient via WindowProxy.
302 script().clearForClose();
303 ScriptForbiddenScope forbidScript
;
305 willDetachFrameHost();
306 InspectorInstrumentation::frameDetachedFromParent(this);
309 // Signal frame destruction here rather than in the destructor.
310 // Main motivation is to avoid being dependent on its exact timing (Oilpan.)
311 LocalFrameLifecycleNotifier::notifyContextDestroyed();
312 m_supplements
.clear();
313 WeakIdentifierMap
<LocalFrame
>::notifyObjectDestroyed(this);
316 bool LocalFrame::prepareForCommit()
318 return loader().prepareForCommit();
321 SecurityContext
* LocalFrame::securityContext() const
326 void LocalFrame::printNavigationErrorMessage(const Frame
& targetFrame
, const char* reason
)
328 // URLs aren't available for RemoteFrames, so the error message uses their
330 String targetFrameDescription
= targetFrame
.isLocalFrame() ? "with URL '" + toLocalFrame(targetFrame
).document()->url().string() + "'" : "with origin '" + targetFrame
.securityContext()->securityOrigin()->toString() + "'";
331 String message
= "Unsafe JavaScript attempt to initiate navigation for frame " + targetFrameDescription
+ " from frame with URL '" + document()->url().string() + "'. " + reason
+ "\n";
333 localDOMWindow()->printErrorMessage(message
);
336 WindowProxyManager
* LocalFrame::windowProxyManager() const
338 return m_script
->windowProxyManager();
341 void LocalFrame::disconnectOwnerElement()
344 if (Document
* document
= this->document())
345 document
->topDocument().clearAXObjectCache();
347 // First give the plugin elements holding persisted,
348 // renderer-less plugins the opportunity to dispose of them.
349 for (const auto& pluginElement
: m_pluginElements
)
350 pluginElement
->disconnectContentFrame();
351 m_pluginElements
.clear();
354 Frame::disconnectOwnerElement();
357 bool LocalFrame::shouldClose()
359 // TODO(dcheng): This should be fixed to dispatch beforeunload events to
360 // both local and remote frames.
361 return m_loader
.shouldClose();
364 void LocalFrame::willDetachFrameHost()
366 LocalFrameLifecycleNotifier::notifyWillDetachFrameHost();
368 // FIXME: Page should take care of updating focus/scrolling instead of Frame.
369 // FIXME: It's unclear as to why this is called more than once, but it is,
370 // so page() could be null.
371 if (page() && page()->focusController().focusedFrame() == this)
372 page()->focusController().setFocusedFrame(nullptr);
373 script().clearScriptObjects();
375 if (page() && page()->scrollingCoordinator() && m_view
)
376 page()->scrollingCoordinator()->willDestroyScrollableArea(m_view
.get());
379 void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr
<LocalDOMWindow
> domWindow
)
381 // Oilpan: setDOMWindow() cannot be used when finalizing. Which
382 // is acceptable as its actions are either not needed or handled
385 // - LocalFrameLifecycleObserver::willDetachFrameHost() will have
386 // signalled the Inspector frameWindowDiscarded() notifications.
387 // We assume that all LocalFrames are detached, where that notification
388 // will have been done.
390 // - Calling LocalDOMWindow::reset() is not needed (called from
391 // Frame::setDOMWindow().) The Member references it clears will now
392 // die with the window. And the registered DOMWindowProperty instances that don't,
393 // only keep a weak reference to this frame, so there's no need to be
394 // explicitly notified that this frame is going away.
395 if (m_domWindow
&& host())
396 host()->consoleMessageStorage().frameWindowDiscarded(m_domWindow
.get());
398 script().clearWindowProxy();
401 m_domWindow
->reset();
402 m_domWindow
= domWindow
;
405 Document
* LocalFrame::document() const
407 return m_domWindow
? m_domWindow
->document() : nullptr;
410 void LocalFrame::setPagePopupOwner(Element
& owner
)
412 m_pagePopupOwner
= &owner
;
415 LayoutView
* LocalFrame::contentLayoutObject() const
417 return document() ? document()->layoutView() : nullptr;
420 void LocalFrame::didChangeVisibilityState()
423 document()->didChangeVisibilityState();
425 WillBeHeapVector
<RefPtrWillBeMember
<LocalFrame
>> childFrames
;
426 for (Frame
* child
= tree().firstChild(); child
; child
= child
->tree().nextSibling()) {
427 if (child
->isLocalFrame())
428 childFrames
.append(toLocalFrame(child
));
431 for (size_t i
= 0; i
< childFrames
.size(); ++i
)
432 childFrames
[i
]->didChangeVisibilityState();
435 LocalFrame
* LocalFrame::localFrameRoot()
437 LocalFrame
* curFrame
= this;
438 while (curFrame
&& curFrame
->tree().parent() && curFrame
->tree().parent()->isLocalFrame())
439 curFrame
= toLocalFrame(curFrame
->tree().parent());
444 String
LocalFrame::layerTreeAsText(LayerTreeFlags flags
) const
446 TextStream textStream
;
447 textStream
<< localLayerTreeAsText(flags
);
449 for (Frame
* child
= tree().firstChild(); child
; child
= child
->tree().traverseNext(this)) {
450 if (!child
->isLocalFrame())
452 String childLayerTree
= toLocalFrame(child
)->localLayerTreeAsText(flags
);
453 if (!childLayerTree
.length())
456 textStream
<< "\n\n--------\nFrame: '";
457 textStream
<< child
->tree().uniqueName();
458 textStream
<< "'\n--------\n";
459 textStream
<< childLayerTree
;
462 return textStream
.release();
465 void LocalFrame::setPrinting(bool printing
, const FloatSize
& pageSize
, const FloatSize
& originalPageSize
, float maximumShrinkRatio
)
467 // In setting printing, we should not validate resources already cached for the document.
468 // See https://bugs.webkit.org/show_bug.cgi?id=43704
469 ResourceCacheValidationSuppressor
validationSuppressor(document()->fetcher());
471 document()->setPrinting(printing
);
472 view()->adjustMediaTypeForPrinting(printing
);
474 document()->styleResolverChanged();
475 if (shouldUsePrintingLayout()) {
476 view()->forceLayoutForPagination(pageSize
, originalPageSize
, maximumShrinkRatio
);
478 if (LayoutView
* layoutView
= view()->layoutView()) {
479 layoutView
->setPreferredLogicalWidthsDirty();
480 layoutView
->setNeedsLayout(LayoutInvalidationReason::PrintingChanged
);
481 layoutView
->setShouldDoFullPaintInvalidationForViewAndAllDescendants();
484 view()->adjustViewSize();
487 // Subframes of the one we're printing don't lay out to the page size.
488 for (RefPtrWillBeRawPtr
<Frame
> child
= tree().firstChild(); child
; child
= child
->tree().nextSibling()) {
489 if (child
->isLocalFrame())
490 toLocalFrame(child
.get())->setPrinting(printing
, FloatSize(), FloatSize(), 0);
494 bool LocalFrame::shouldUsePrintingLayout() const
496 // Only top frame being printed should be fit to page size.
497 // Subframes should be constrained by parents only.
498 return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing());
501 FloatSize
LocalFrame::resizePageRectsKeepingRatio(const FloatSize
& originalSize
, const FloatSize
& expectedSize
)
503 FloatSize resultSize
;
504 if (!contentLayoutObject())
507 if (contentLayoutObject()->style()->isHorizontalWritingMode()) {
508 ASSERT(fabs(originalSize
.width()) > std::numeric_limits
<float>::epsilon());
509 float ratio
= originalSize
.height() / originalSize
.width();
510 resultSize
.setWidth(floorf(expectedSize
.width()));
511 resultSize
.setHeight(floorf(resultSize
.width() * ratio
));
513 ASSERT(fabs(originalSize
.height()) > std::numeric_limits
<float>::epsilon());
514 float ratio
= originalSize
.width() / originalSize
.height();
515 resultSize
.setHeight(floorf(expectedSize
.height()));
516 resultSize
.setWidth(floorf(resultSize
.height() * ratio
));
521 void LocalFrame::setPageZoomFactor(float factor
)
523 setPageAndTextZoomFactors(factor
, m_textZoomFactor
);
526 void LocalFrame::setTextZoomFactor(float factor
)
528 setPageAndTextZoomFactors(m_pageZoomFactor
, factor
);
531 void LocalFrame::setPageAndTextZoomFactors(float pageZoomFactor
, float textZoomFactor
)
533 if (m_pageZoomFactor
== pageZoomFactor
&& m_textZoomFactor
== textZoomFactor
)
536 Page
* page
= this->page();
540 Document
* document
= this->document();
544 // Respect SVGs zoomAndPan="disabled" property in standalone SVG documents.
545 // FIXME: How to handle compound documents + zoomAndPan="disabled"? Needs SVG WG clarification.
546 if (document
->isSVGDocument()) {
547 if (!document
->accessSVGExtensions().zoomAndPanEnabled())
551 if (m_pageZoomFactor
!= pageZoomFactor
) {
552 if (FrameView
* view
= this->view()) {
553 // Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
554 LayoutPoint scrollPosition
= view
->scrollPosition();
555 float percentDifference
= (pageZoomFactor
/ m_pageZoomFactor
);
556 view
->setScrollPosition(
557 DoublePoint(scrollPosition
.x() * percentDifference
, scrollPosition
.y() * percentDifference
),
562 m_pageZoomFactor
= pageZoomFactor
;
563 m_textZoomFactor
= textZoomFactor
;
565 for (RefPtrWillBeRawPtr
<Frame
> child
= tree().firstChild(); child
; child
= child
->tree().nextSibling()) {
566 if (child
->isLocalFrame())
567 toLocalFrame(child
.get())->setPageAndTextZoomFactors(m_pageZoomFactor
, m_textZoomFactor
);
570 document
->setNeedsStyleRecalc(SubtreeStyleChange
, StyleChangeReasonForTracing::create(StyleChangeReason::Zoom
));
571 document
->updateLayoutIgnorePendingStylesheets();
574 void LocalFrame::deviceScaleFactorChanged()
576 document()->mediaQueryAffectingValueChanged();
577 for (RefPtrWillBeRawPtr
<Frame
> child
= tree().firstChild(); child
; child
= child
->tree().nextSibling()) {
578 if (child
->isLocalFrame())
579 toLocalFrame(child
.get())->deviceScaleFactorChanged();
583 double LocalFrame::devicePixelRatio() const
588 double ratio
= m_host
->deviceScaleFactor();
589 ratio
*= pageZoomFactor();
593 PassOwnPtr
<DragImage
> LocalFrame::paintIntoDragImage(
594 const DisplayItemClientWrapper
& displayItemClient
,
595 RespectImageOrientationEnum shouldRespectImageOrientation
,
596 const GlobalPaintFlags globalPaintFlags
, IntRect paintingRect
, float opacity
)
598 ASSERT(document()->isActive());
599 // Not flattening compositing layers will result in a broken image being painted.
600 ASSERT(globalPaintFlags
& GlobalPaintFlattenCompositingLayers
);
602 float deviceScaleFactor
= m_host
->deviceScaleFactor();
603 paintingRect
.setWidth(paintingRect
.width() * deviceScaleFactor
);
604 paintingRect
.setHeight(paintingRect
.height() * deviceScaleFactor
);
606 // The content is shifted to origin, to fit within the image bounds - which are the same
607 // as the picture bounds.
608 SkRect pictureBounds
= SkRect::MakeIWH(paintingRect
.width(), paintingRect
.height());
609 SkPictureBuilder
pictureBuilder(pictureBounds
);
611 GraphicsContext
& paintContext
= pictureBuilder
.context();
613 AffineTransform transform
;
614 transform
.scale(deviceScaleFactor
, deviceScaleFactor
);
615 transform
.translate(-paintingRect
.x(), -paintingRect
.y());
616 TransformRecorder
transformRecorder(paintContext
, displayItemClient
, transform
);
618 m_view
->paintContents(&paintContext
, globalPaintFlags
, paintingRect
);
621 RefPtr
<const SkPicture
> recording
= pictureBuilder
.endRecording();
622 RefPtr
<SkImage
> skImage
= adoptRef(SkImage::NewFromPicture(recording
.get(),
623 SkISize::Make(paintingRect
.width(), paintingRect
.height()), nullptr, nullptr));
624 RefPtr
<Image
> image
= StaticBitmapImage::create(skImage
.release());
626 return DragImage::create(image
.get(), shouldRespectImageOrientation
, deviceScaleFactor
,
627 InterpolationHigh
, opacity
);
630 PassOwnPtr
<DragImage
> LocalFrame::nodeImage(Node
& node
)
632 if (!node
.layoutObject())
635 const ScopedFramePaintingState
state(this, &node
);
637 m_view
->updateAllLifecyclePhases();
639 m_view
->setNodeToDraw(&node
); // Enable special sub-tree drawing mode.
641 // Document::updateLayout may have blown away the original LayoutObject.
642 LayoutObject
* layoutObject
= node
.layoutObject();
648 return paintIntoDragImage(*layoutObject
, layoutObject
->shouldRespectImageOrientation(),
649 GlobalPaintFlattenCompositingLayers
, layoutObject
->paintingRootRect(rect
));
652 PassOwnPtr
<DragImage
> LocalFrame::dragImageForSelection(float opacity
)
654 if (!selection().isRange())
657 const ScopedFramePaintingState
state(this, 0);
658 m_view
->updateAllLifecyclePhases();
660 return paintIntoDragImage(*this, DoNotRespectImageOrientation
,
661 GlobalPaintSelectionOnly
| GlobalPaintFlattenCompositingLayers
,
662 enclosingIntRect(selection().bounds()), opacity
);
665 String
LocalFrame::selectedText() const
667 return selection().selectedText();
670 String
LocalFrame::selectedTextForClipboard() const
672 return selection().selectedTextForClipboard();
675 VisiblePosition
LocalFrame::visiblePositionForPoint(const IntPoint
& framePoint
)
677 HitTestResult result
= eventHandler().hitTestResultAtPoint(framePoint
);
678 Node
* node
= result
.innerNodeOrImageMapImage();
680 return VisiblePosition();
681 LayoutObject
* layoutObject
= node
->layoutObject();
683 return VisiblePosition();
684 VisiblePosition visiblePos
= VisiblePosition(layoutObject
->positionForPoint(result
.localPoint()));
685 if (visiblePos
.isNull())
686 visiblePos
= VisiblePosition(firstPositionInOrBeforeNode(node
));
690 Document
* LocalFrame::documentAtPoint(const IntPoint
& pointInRootFrame
)
695 IntPoint pt
= view()->rootFrameToContents(pointInRootFrame
);
697 if (!contentLayoutObject())
699 HitTestResult result
= eventHandler().hitTestResultAtPoint(pt
, HitTestRequest::ReadOnly
| HitTestRequest::Active
);
700 return result
.innerNode() ? &result
.innerNode()->document() : nullptr;
703 EphemeralRange
LocalFrame::rangeForPoint(const IntPoint
& framePoint
)
705 VisiblePosition position
= visiblePositionForPoint(framePoint
);
706 if (position
.isNull())
707 return EphemeralRange();
709 VisiblePosition previous
= position
.previous();
710 if (previous
.isNotNull()) {
711 const EphemeralRange previousCharacterRange
= makeRange(previous
, position
);
712 IntRect rect
= editor().firstRectForRange(previousCharacterRange
);
713 if (rect
.contains(framePoint
))
714 return EphemeralRange(previousCharacterRange
);
717 VisiblePosition next
= position
.next();
718 const EphemeralRange nextCharacterRange
= makeRange(position
, next
);
719 if (nextCharacterRange
.isNotNull()) {
720 IntRect rect
= editor().firstRectForRange(nextCharacterRange
);
721 if (rect
.contains(framePoint
))
722 return EphemeralRange(nextCharacterRange
);
725 return EphemeralRange();
728 bool LocalFrame::isURLAllowed(const KURL
& url
) const
730 // We allow one level of self-reference because some sites depend on that,
731 // but we don't allow more than one.
732 bool foundSelfReference
= false;
733 for (const Frame
* frame
= this; frame
; frame
= frame
->tree().parent()) {
734 if (!frame
->isLocalFrame())
736 if (equalIgnoringFragmentIdentifier(toLocalFrame(frame
)->document()->url(), url
)) {
737 if (foundSelfReference
)
739 foundSelfReference
= true;
745 bool LocalFrame::shouldReuseDefaultView(const KURL
& url
) const
747 return loader().stateMachine()->isDisplayingInitialEmptyDocument() && document()->isSecureTransitionTo(url
);
750 void LocalFrame::removeSpellingMarkersUnderWords(const Vector
<String
>& words
)
752 spellChecker().removeSpellingMarkersUnderWords(words
);
755 static ScrollResult
scrollAreaOnBothAxes(const FloatSize
& delta
, ScrollableArea
& view
)
757 ScrollResultOneDimensional scrolledHorizontal
= view
.userScroll(ScrollLeft
, ScrollByPrecisePixel
, delta
.width());
758 ScrollResultOneDimensional scrolledVertical
= view
.userScroll(ScrollUp
, ScrollByPrecisePixel
, delta
.height());
759 return ScrollResult(scrolledHorizontal
.didScroll
, scrolledVertical
.didScroll
, scrolledHorizontal
.unusedScrollDelta
, scrolledVertical
.unusedScrollDelta
);
762 // Returns true if a scroll occurred.
763 ScrollResult
LocalFrame::applyScrollDelta(const FloatSize
& delta
, bool isScrollBegin
)
766 host()->topControls().scrollBegin();
768 if (!view() || delta
.isZero())
769 return ScrollResult(false, false, delta
.width(), delta
.height());
771 FloatSize remainingDelta
= delta
;
773 // If this is main frame, allow top controls to scroll first.
774 if (shouldScrollTopControls(delta
))
775 remainingDelta
= host()->topControls().scrollBy(remainingDelta
);
777 if (remainingDelta
.isZero())
778 return ScrollResult(delta
.width(), delta
.height(), 0.0f
, 0.0f
);
780 ScrollResult result
= scrollAreaOnBothAxes(remainingDelta
, *view()->scrollableArea());
781 result
.didScrollX
= result
.didScrollX
|| (remainingDelta
.width() != delta
.width());
782 result
.didScrollY
= result
.didScrollY
|| (remainingDelta
.height() != delta
.height());
787 bool LocalFrame::shouldScrollTopControls(const FloatSize
& delta
) const
792 // Always give the delta to the top controls if the scroll is in
793 // the direction to show the top controls. If it's in the
794 // direction to hide the top controls, only give the delta to the
795 // top controls when the frame can scroll.
796 DoublePoint maximumScrollPosition
=
797 host()->visualViewport().maximumScrollPositionDouble() +
798 toDoubleSize(view()->maximumScrollPositionDouble());
799 DoublePoint scrollPosition
= host()->visualViewport()
800 .visibleRectInDocument().location();
801 return delta
.height() > 0 || scrollPosition
.y() < maximumScrollPosition
.y();
805 void LocalFrame::registerPluginElement(HTMLPlugInElement
* plugin
)
807 m_pluginElements
.add(plugin
);
810 void LocalFrame::unregisterPluginElement(HTMLPlugInElement
* plugin
)
812 ASSERT(m_pluginElements
.contains(plugin
));
813 m_pluginElements
.remove(plugin
);
816 void LocalFrame::clearWeakMembers(Visitor
* visitor
)
818 Vector
<HTMLPlugInElement
*> deadPlugins
;
819 for (const auto& pluginElement
: m_pluginElements
) {
820 if (!Heap::isHeapObjectAlive(pluginElement
)) {
821 pluginElement
->shouldDisposePlugin();
822 deadPlugins
.append(pluginElement
);
825 for (unsigned i
= 0; i
< deadPlugins
.size(); ++i
)
826 m_pluginElements
.remove(deadPlugins
[i
]);
830 String
LocalFrame::localLayerTreeAsText(unsigned flags
) const
832 if (!contentLayoutObject())
835 return contentLayoutObject()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags
>(flags
));
838 inline LocalFrame::LocalFrame(FrameLoaderClient
* client
, FrameHost
* host
, FrameOwner
* owner
)
839 : Frame(client
, host
, owner
)
841 , m_navigationScheduler(this)
842 , m_script(ScriptController::create(this))
843 , m_editor(Editor::create(*this))
844 , m_spellChecker(SpellChecker::create(*this))
845 , m_selection(FrameSelection::create(this))
846 , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this)))
847 , m_console(FrameConsole::create(*this))
848 , m_inputMethodController(InputMethodController::create(*this))
849 , m_pageZoomFactor(parentPageZoomFactor(this))
850 , m_textZoomFactor(parentTextZoomFactor(this))
851 , m_inViewSourceMode(false)
854 m_instrumentingAgents
= InstrumentingAgents::create();
856 m_instrumentingAgents
= localFrameRoot()->m_instrumentingAgents
;
859 DEFINE_WEAK_IDENTIFIER_MAP(LocalFrame
);