#include "core/frame/LocalDOMWindow.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLFrameElementBase.h"
+#include "core/html/HTMLPlugInElement.h"
#include "core/inspector/ConsoleMessageStorage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/loader/FrameLoaderClient.h"
using namespace HTMLNames;
-static inline float parentPageZoomFactor(LocalFrame* frame)
+namespace {
+
+struct ScopedFramePaintingState {
+ ScopedFramePaintingState(LocalFrame* frame, Node* node)
+ : frame(frame)
+ , node(node)
+ , paintBehavior(frame->view()->paintBehavior())
+ {
+ ASSERT(!node || node->renderer());
+ if (node)
+ node->renderer()->updateDragState(true);
+ }
+
+ ~ScopedFramePaintingState()
+ {
+ if (node && node->renderer())
+ node->renderer()->updateDragState(false);
+ frame->view()->setPaintBehavior(paintBehavior);
+ frame->view()->setNodeToDraw(0);
+ }
+
+ LocalFrame* frame;
+ Node* node;
+ PaintBehavior paintBehavior;
+};
+
+inline float parentPageZoomFactor(LocalFrame* frame)
{
Frame* parent = frame->tree().parent();
if (!parent || !parent->isLocalFrame())
return toLocalFrame(parent)->pageZoomFactor();
}
-static inline float parentTextZoomFactor(LocalFrame* frame)
+inline float parentTextZoomFactor(LocalFrame* frame)
{
Frame* parent = frame->tree().parent();
if (!parent || !parent->isLocalFrame())
return toLocalFrame(parent)->textZoomFactor();
}
-inline LocalFrame::LocalFrame(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
- : Frame(client, host, owner)
- , m_loader(this)
- , m_navigationScheduler(this)
- , m_script(adoptPtr(new ScriptController(this)))
- , m_editor(Editor::create(*this))
- , m_spellChecker(SpellChecker::create(*this))
- , m_selection(FrameSelection::create(this))
- , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this)))
- , m_console(FrameConsole::create(*this))
- , m_inputMethodController(InputMethodController::create(*this))
- , m_pageZoomFactor(parentPageZoomFactor(this))
- , m_textZoomFactor(parentTextZoomFactor(this))
- , m_inViewSourceMode(false)
-{
-}
+} // namespace
PassRefPtrWillBeRawPtr<LocalFrame> LocalFrame::create(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
{
return frame.release();
}
+void LocalFrame::setView(PassRefPtrWillBeRawPtr<FrameView> view)
+{
+ ASSERT(!m_view || m_view != view);
+ detachView();
+
+ // Prepare for destruction now, so any unload event handlers get run and the LocalDOMWindow is
+ // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
+ // these calls to work.
+ if (!view && document() && document()->isActive()) {
+ // FIXME: We don't call willRemove here. Why is that OK?
+ document()->prepareForDestruction();
+ }
+
+ eventHandler().clear();
+
+ m_view = view;
+
+ if (m_view && isMainFrame() && !settings()->pinchVirtualViewportEnabled())
+ m_view->setVisibleContentScaleFactor(page()->pageScaleFactor());
+}
+
+void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
+ ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
+ ScrollbarMode verticalScrollbarMode, bool verticalLock)
+{
+ ASSERT(this);
+ ASSERT(page());
+
+ bool isLocalRoot = this->isLocalRoot();
+
+ if (isLocalRoot && view())
+ view()->setParentVisible(false);
+
+ setView(nullptr);
+
+ RefPtrWillBeRawPtr<FrameView> frameView = nullptr;
+ if (isLocalRoot) {
+ frameView = FrameView::create(this, viewportSize);
+
+ // The layout size is set by WebViewImpl to support @viewport
+ frameView->setLayoutSizeFixedToFrameSize(false);
+ } else {
+ frameView = FrameView::create(this);
+ }
+
+ frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
+
+ setView(frameView);
+
+ frameView->updateBackgroundRecursively(backgroundColor, transparent);
+
+ if (isLocalRoot)
+ frameView->setParentVisible(true);
+
+ // FIXME: Not clear what the right thing for OOPI is here.
+ if (ownerRenderer()) {
+ HTMLFrameOwnerElement* owner = deprecatedLocalOwner();
+ ASSERT(owner);
+ // FIXME: OOPI might lead to us temporarily lying to a frame and telling it
+ // that it's owned by a FrameOwner that knows nothing about it. If we're
+ // lying to this frame, don't let it clobber the existing widget.
+ if (owner->contentFrame() == this)
+ owner->setWidget(frameView);
+ }
+
+ if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner())
+ view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
+}
+
LocalFrame::~LocalFrame()
{
#if ENABLE(OILPAN)
m_loader.clear();
setDOMWindow(nullptr);
- HashSet<RawPtr<FrameDestructionObserver> >::iterator stop = m_destructionObservers.end();
- for (HashSet<RawPtr<FrameDestructionObserver> >::iterator it = m_destructionObservers.begin(); it != stop; ++it)
- (*it)->frameDestroyed();
+ for (const auto& frameDestructionObserver : m_destructionObservers)
+ frameDestructionObserver->frameDestroyed();
#endif
}
visitor->trace(m_destructionObservers);
visitor->trace(m_loader);
visitor->trace(m_navigationScheduler);
+ visitor->trace(m_view);
+ visitor->trace(m_domWindow);
visitor->trace(m_pagePopupOwner);
+ visitor->trace(m_script);
visitor->trace(m_editor);
visitor->trace(m_spellChecker);
visitor->trace(m_selection);
visitor->trace(m_eventHandler);
visitor->trace(m_console);
visitor->trace(m_inputMethodController);
+ visitor->registerWeakMembers<LocalFrame, &LocalFrame::clearWeakMembers>(this);
HeapSupplementable<LocalFrame>::trace(visitor);
#endif
Frame::trace(visitor);
}
+LocalDOMWindow* LocalFrame::domWindow() const
+{
+ return m_domWindow.get();
+}
+
+void LocalFrame::navigate(Document& originDocument, const KURL& url, bool lockBackForwardList)
+{
+ m_navigationScheduler.scheduleLocationChange(&originDocument, url.string(), lockBackForwardList);
+}
+
void LocalFrame::detach()
{
// A lot of the following steps can result in the current frame being
// will trigger the unload event handlers of any child frames, and those event
// handlers might start a new subresource load in this frame.
m_loader.stopAllLoaders();
- m_loader.detachFromParent();
-}
-
-bool LocalFrame::inScope(TreeScope* scope) const
-{
- ASSERT(scope);
- Document* doc = document();
- if (!doc)
- return false;
- // FIXME: This check is broken in for OOPI.
- HTMLFrameOwnerElement* owner = doc->ownerElement();
- if (!owner)
- return false;
- return owner->treeScope() == scope;
-}
-
-void LocalFrame::detachView()
-{
- // We detach the FrameView's custom scroll bars as early as
- // possible to prevent m_doc->detach() from messing with the view
- // such that its scroll bars won't be torn down.
- //
- // FIXME: We should revisit this.
- if (m_view)
- m_view->prepareForDetach();
-}
-
-void LocalFrame::setView(PassRefPtr<FrameView> view)
-{
- detachView();
-
- // Prepare for destruction now, so any unload event handlers get run and the LocalDOMWindow is
- // notified. If we wait until the view is destroyed, then things won't be hooked up enough for
- // these calls to work.
- if (!view && document() && document()->isActive()) {
- // FIXME: We don't call willRemove here. Why is that OK?
- document()->prepareForDestruction();
- }
-
- eventHandler().clear();
-
- m_view = view;
-
- if (m_view && isMainFrame()) {
- if (settings()->pinchVirtualViewportEnabled())
- m_host->pinchViewport().mainFrameDidChangeSize();
- else
- m_view->setVisibleContentScaleFactor(page()->pageScaleFactor());
- }
-}
-
-void LocalFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio)
-{
- // In setting printing, we should not validate resources already cached for the document.
- // See https://bugs.webkit.org/show_bug.cgi?id=43704
- ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher());
-
- document()->setPrinting(printing);
- view()->adjustMediaTypeForPrinting(printing);
-
- document()->styleResolverChanged();
- if (shouldUsePrintingLayout()) {
- view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio);
- } else {
- view()->forceLayout();
- view()->adjustViewSize();
- }
-
- // Subframes of the one we're printing don't lay out to the page size.
- for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
- if (child->isLocalFrame())
- toLocalFrame(child.get())->setPrinting(printing, FloatSize(), FloatSize(), 0);
- }
-}
-
-bool LocalFrame::shouldUsePrintingLayout() const
-{
- // Only top frame being printed should be fit to page size.
- // Subframes should be constrained by parents only.
- return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing());
-}
-
-FloatSize LocalFrame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
-{
- FloatSize resultSize;
- if (!contentRenderer())
- return FloatSize();
-
- if (contentRenderer()->style()->isHorizontalWritingMode()) {
- ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
- float ratio = originalSize.height() / originalSize.width();
- resultSize.setWidth(floorf(expectedSize.width()));
- resultSize.setHeight(floorf(resultSize.width() * ratio));
- } else {
- ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
- float ratio = originalSize.width() / originalSize.height();
- resultSize.setHeight(floorf(expectedSize.height()));
- resultSize.setWidth(floorf(resultSize.height() * ratio));
- }
- return resultSize;
-}
-
-void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)
-{
- if (m_domWindow) {
- // Oilpan: the assumption is that FrameDestructionObserver::willDetachFrameHost()
- // on LocalWindow will have signalled these frameWindowDiscarded() notifications.
- //
- // It is not invoked when finalizing the LocalFrame, as setDOMWindow() isn't
- // performed (accessing the m_domWindow heap object is unsafe then.)
- console().messageStorage()->frameWindowDiscarded(m_domWindow.get());
- InspectorInstrumentation::frameWindowDiscarded(this, m_domWindow.get());
- }
- if (domWindow)
- script().clearWindowProxy();
- Frame::setDOMWindow(domWindow);
+ if (!client())
+ return;
+ m_loader.detach();
+ setView(nullptr);
+ willDetachFrameHost();
+ // Notify ScriptController that the frame is closing, since its cleanup ends up calling
+ // back to FrameLoaderClient via WindowProxy.
+ script().clearForClose();
+ InspectorInstrumentation::frameDetachedFromParent(this);
+ Frame::detach();
+#if ENABLE(OILPAN)
+ // Clear the FrameLoader right here rather than during
+ // finalization. Too late to access various heap objects at that
+ // stage.
+ loader().clear();
+#endif
}
-void LocalFrame::didChangeVisibilityState()
+void LocalFrame::disconnectOwnerElement()
{
- if (document())
- document()->didChangeVisibilityState();
-
- WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > childFrames;
- for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) {
- if (child->isLocalFrame())
- childFrames.append(toLocalFrame(child));
+ if (owner()) {
+ if (Document* document = this->document())
+ document->topDocument().clearAXObjectCache();
+#if ENABLE(OILPAN)
+ // First give the plugin elements holding persisted,
+ // renderer-less plugins the opportunity to dispose of them.
+ for (const auto& pluginElement : m_pluginElements)
+ pluginElement->disconnectContentFrame();
+ m_pluginElements.clear();
+#endif
}
-
- for (size_t i = 0; i < childFrames.size(); ++i)
- childFrames[i]->didChangeVisibilityState();
+ Frame::disconnectOwnerElement();
}
void LocalFrame::addDestructionObserver(FrameDestructionObserver* observer)
void LocalFrame::willDetachFrameHost()
{
- // We should never be detatching the page during a Layout.
- RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout());
-
- Frame* parent = tree().parent();
- if (parent && parent->isLocalFrame())
- toLocalFrame(parent)->loader().checkLoadComplete();
- WillBeHeapHashSet<RawPtrWillBeWeakMember<FrameDestructionObserver> >::iterator stop = m_destructionObservers.end();
- for (WillBeHeapHashSet<RawPtrWillBeWeakMember<FrameDestructionObserver> >::iterator it = m_destructionObservers.begin(); it != stop; ++it)
- (*it)->willDetachFrameHost();
+ for (const auto& frameDestructionObserver : m_destructionObservers)
+ frameDestructionObserver->willDetachFrameHost();
// FIXME: Page should take care of updating focus/scrolling instead of Frame.
// FIXME: It's unclear as to why this is called more than once, but it is,
page()->scrollingCoordinator()->willDestroyScrollableArea(m_view.get());
}
-void LocalFrame::detachFromFrameHost()
-{
- // We should never be detaching the page during a Layout.
- RELEASE_ASSERT(!m_view || !m_view->isInPerformLayout());
- m_host = nullptr;
-}
-
-String LocalFrame::documentTypeString() const
+void LocalFrame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)
{
- if (DocumentType* doctype = document()->doctype())
- return createMarkup(doctype);
-
- return String();
-}
+ // Oilpan: setDOMWindow() cannot be used when finalizing. Which
+ // is acceptable as its actions are either not needed or handled
+ // by other means --
+ //
+ // - FrameDestructionObserver::willDetachFrameHost() will have
+ // signalled the Inspector frameWindowDiscarded() notifications.
+ // We assume that all LocalFrames are detached, where that notification
+ // will have been done.
+ //
+ // - Calling LocalDOMWindow::reset() is not needed (called from
+ // Frame::setDOMWindow().) The Member references it clears will now
+ // die with the window. And the registered DOMWindowProperty instances that don't,
+ // only keep a weak reference to this frame, so there's no need to be
+ // explicitly notified that this frame is going away.
+ if (m_domWindow && host()) {
+ host()->consoleMessageStorage().frameWindowDiscarded(m_domWindow.get());
+ InspectorInstrumentation::frameWindowDiscarded(this, m_domWindow.get());
+ }
+ if (domWindow)
+ script().clearWindowProxy();
-String LocalFrame::selectedText() const
-{
- return selection().selectedText();
+ if (m_domWindow)
+ m_domWindow->reset();
+ m_domWindow = domWindow;
}
-String LocalFrame::selectedTextForClipboard() const
+Document* LocalFrame::document() const
{
- return selection().selectedTextForClipboard();
+ return m_domWindow ? m_domWindow->document() : 0;
}
-VisiblePosition LocalFrame::visiblePositionForPoint(const IntPoint& framePoint)
+void LocalFrame::setPagePopupOwner(Element& owner)
{
- HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint);
- Node* node = result.innerNonSharedNode();
- if (!node)
- return VisiblePosition();
- RenderObject* renderer = node->renderer();
- if (!renderer)
- return VisiblePosition();
- VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint()));
- if (visiblePos.isNull())
- visiblePos = VisiblePosition(firstPositionInOrBeforeNode(node));
- return visiblePos;
+ m_pagePopupOwner = &owner;
}
RenderView* LocalFrame::contentRenderer() const
return document() ? document()->renderView() : 0;
}
-Document* LocalFrame::document() const
-{
- return m_domWindow ? m_domWindow->document() : 0;
-}
-
-Document* LocalFrame::documentAtPoint(const IntPoint& point)
-{
- if (!view())
- return 0;
-
- IntPoint pt = view()->windowToContents(point);
- HitTestResult result = HitTestResult(pt);
-
- if (contentRenderer())
- result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active);
- return result.innerNode() ? &result.innerNode()->document() : 0;
-}
-
-PassRefPtrWillBeRawPtr<Range> LocalFrame::rangeForPoint(const IntPoint& framePoint)
+void LocalFrame::didChangeVisibilityState()
{
- VisiblePosition position = visiblePositionForPoint(framePoint);
- if (position.isNull())
- return nullptr;
-
- VisiblePosition previous = position.previous();
- if (previous.isNotNull()) {
- RefPtrWillBeRawPtr<Range> previousCharacterRange = makeRange(previous, position);
- LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
- if (rect.contains(framePoint))
- return previousCharacterRange.release();
- }
+ if (document())
+ document()->didChangeVisibilityState();
- VisiblePosition next = position.next();
- if (RefPtrWillBeRawPtr<Range> nextCharacterRange = makeRange(position, next)) {
- LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
- if (rect.contains(framePoint))
- return nextCharacterRange.release();
+ WillBeHeapVector<RefPtrWillBeMember<LocalFrame> > childFrames;
+ for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling()) {
+ if (child->isLocalFrame())
+ childFrames.append(toLocalFrame(child));
}
- return nullptr;
+ for (size_t i = 0; i < childFrames.size(); ++i)
+ childFrames[i]->didChangeVisibilityState();
}
-void LocalFrame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent,
- ScrollbarMode horizontalScrollbarMode, bool horizontalLock,
- ScrollbarMode verticalScrollbarMode, bool verticalLock)
+LocalFrame* LocalFrame::localFrameRoot()
{
- ASSERT(this);
- ASSERT(page());
-
- bool isLocalRoot = this->isLocalRoot();
-
- if (isLocalRoot && view())
- view()->setParentVisible(false);
-
- setView(nullptr);
-
- RefPtr<FrameView> frameView;
- if (isLocalRoot) {
- frameView = FrameView::create(this, viewportSize);
-
- // The layout size is set by WebViewImpl to support @viewport
- frameView->setLayoutSizeFixedToFrameSize(false);
- } else
- frameView = FrameView::create(this);
-
- frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode, horizontalLock, verticalLock);
-
- setView(frameView);
-
- frameView->updateBackgroundRecursively(backgroundColor, transparent);
-
- if (isLocalRoot)
- frameView->setParentVisible(true);
-
- // FIXME: Not clear what the right thing for OOPI is here.
- if (ownerRenderer()) {
- HTMLFrameOwnerElement* owner = deprecatedLocalOwner();
- ASSERT(owner);
- owner->setWidget(frameView);
- }
+ LocalFrame* curFrame = this;
+ while (curFrame && curFrame->tree().parent() && curFrame->tree().parent()->isLocalFrame())
+ curFrame = toLocalFrame(curFrame->tree().parent());
- if (HTMLFrameOwnerElement* owner = deprecatedLocalOwner())
- view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);
+ return curFrame;
}
+bool LocalFrame::inScope(TreeScope* scope) const
+{
+ ASSERT(scope);
+ Document* doc = document();
+ if (!doc)
+ return false;
+ // FIXME: This check is broken in for OOPI.
+ HTMLFrameOwnerElement* owner = doc->ownerElement();
+ if (!owner)
+ return false;
+ return owner->treeScope() == scope;
+}
void LocalFrame::countObjectsNeedingLayout(unsigned& needsLayoutObjects, unsigned& totalObjects, bool& isPartial)
{
return textStream.release();
}
-String LocalFrame::localLayerTreeAsText(unsigned flags) const
+void LocalFrame::setPrinting(bool printing, const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkRatio)
+{
+ // In setting printing, we should not validate resources already cached for the document.
+ // See https://bugs.webkit.org/show_bug.cgi?id=43704
+ ResourceCacheValidationSuppressor validationSuppressor(document()->fetcher());
+
+ document()->setPrinting(printing);
+ view()->adjustMediaTypeForPrinting(printing);
+
+ document()->styleResolverChanged();
+ if (shouldUsePrintingLayout()) {
+ view()->forceLayoutForPagination(pageSize, originalPageSize, maximumShrinkRatio);
+ } else {
+ view()->forceLayout();
+ view()->adjustViewSize();
+ }
+
+ // Subframes of the one we're printing don't lay out to the page size.
+ for (RefPtrWillBeRawPtr<Frame> child = tree().firstChild(); child; child = child->tree().nextSibling()) {
+ if (child->isLocalFrame())
+ toLocalFrame(child.get())->setPrinting(printing, FloatSize(), FloatSize(), 0);
+ }
+}
+
+bool LocalFrame::shouldUsePrintingLayout() const
+{
+ // Only top frame being printed should be fit to page size.
+ // Subframes should be constrained by parents only.
+ return document()->printing() && (!tree().parent() || !tree().parent()->isLocalFrame() || !toLocalFrame(tree().parent())->document()->printing());
+}
+
+FloatSize LocalFrame::resizePageRectsKeepingRatio(const FloatSize& originalSize, const FloatSize& expectedSize)
{
+ FloatSize resultSize;
if (!contentRenderer())
- return String();
+ return FloatSize();
- return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags));
+ if (contentRenderer()->style()->isHorizontalWritingMode()) {
+ ASSERT(fabs(originalSize.width()) > std::numeric_limits<float>::epsilon());
+ float ratio = originalSize.height() / originalSize.width();
+ resultSize.setWidth(floorf(expectedSize.width()));
+ resultSize.setHeight(floorf(resultSize.width() * ratio));
+ } else {
+ ASSERT(fabs(originalSize.height()) > std::numeric_limits<float>::epsilon());
+ float ratio = originalSize.width() / originalSize.height();
+ resultSize.setHeight(floorf(expectedSize.height()));
+ resultSize.setWidth(floorf(resultSize.height() * ratio));
+ }
+ return resultSize;
}
void LocalFrame::setPageZoomFactor(float factor)
// Update the scroll position when doing a full page zoom, so the content stays in relatively the same position.
LayoutPoint scrollPosition = view->scrollPosition();
float percentDifference = (pageZoomFactor / m_pageZoomFactor);
- view->setScrollPosition(IntPoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
+ view->setScrollPosition(DoublePoint(scrollPosition.x() * percentDifference, scrollPosition.y() * percentDifference));
}
}
toLocalFrame(child.get())->setPageAndTextZoomFactors(m_pageZoomFactor, m_textZoomFactor);
}
- document->setNeedsStyleRecalc(SubtreeStyleChange);
+ document->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Zoom));
document->updateLayoutIgnorePendingStylesheets();
}
}
}
-bool LocalFrame::isURLAllowed(const KURL& url) const
+double LocalFrame::devicePixelRatio() const
{
- // We allow one level of self-reference because some sites depend on that,
- // but we don't allow more than one.
- if (page()->subframeCount() >= Page::maxNumberOfFrames)
- return false;
- bool foundSelfReference = false;
- for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
- if (!frame->isLocalFrame())
- continue;
- if (equalIgnoringFragmentIdentifier(toLocalFrame(frame)->document()->url(), url)) {
- if (foundSelfReference)
- return false;
- foundSelfReference = true;
- }
- }
- return true;
-}
+ if (!m_host)
+ return 0;
-bool LocalFrame::shouldReuseDefaultView(const KURL& url) const
-{
- return loader().stateMachine()->isDisplayingInitialEmptyDocument() && document()->isSecureTransitionTo(url);
+ double ratio = m_host->deviceScaleFactor();
+ ratio *= pageZoomFactor();
+ return ratio;
}
-void LocalFrame::removeSpellingMarkersUnderWords(const Vector<String>& words)
+String LocalFrame::documentTypeString() const
{
- spellChecker().removeSpellingMarkersUnderWords(words);
-}
-
-struct ScopedFramePaintingState {
- ScopedFramePaintingState(LocalFrame* frame, Node* node)
- : frame(frame)
- , node(node)
- , paintBehavior(frame->view()->paintBehavior())
- {
- ASSERT(!node || node->renderer());
- if (node)
- node->renderer()->updateDragState(true);
- }
-
- ~ScopedFramePaintingState()
- {
- if (node && node->renderer())
- node->renderer()->updateDragState(false);
- frame->view()->setPaintBehavior(paintBehavior);
- frame->view()->setNodeToDraw(0);
- }
+ if (DocumentType* doctype = document()->doctype())
+ return createMarkup(doctype);
- LocalFrame* frame;
- Node* node;
- PaintBehavior paintBehavior;
-};
+ return String();
+}
PassOwnPtr<DragImage> LocalFrame::nodeImage(Node& node)
{
return DragImage::create(image.get(), DoNotRespectImageOrientation, deviceScaleFactor);
}
-double LocalFrame::devicePixelRatio() const
+String LocalFrame::selectedText() const
{
- if (!m_host)
+ return selection().selectedText();
+}
+
+String LocalFrame::selectedTextForClipboard() const
+{
+ return selection().selectedTextForClipboard();
+}
+
+VisiblePosition LocalFrame::visiblePositionForPoint(const IntPoint& framePoint)
+{
+ HitTestResult result = eventHandler().hitTestResultAtPoint(framePoint);
+ Node* node = result.innerNonSharedNode();
+ if (!node)
+ return VisiblePosition();
+ RenderObject* renderer = node->renderer();
+ if (!renderer)
+ return VisiblePosition();
+ VisiblePosition visiblePos = VisiblePosition(renderer->positionForPoint(result.localPoint()));
+ if (visiblePos.isNull())
+ visiblePos = VisiblePosition(firstPositionInOrBeforeNode(node));
+ return visiblePos;
+}
+
+Document* LocalFrame::documentAtPoint(const IntPoint& point)
+{
+ if (!view())
return 0;
- double ratio = m_host->deviceScaleFactor();
- ratio *= pageZoomFactor();
- return ratio;
+ IntPoint pt = view()->windowToContents(point);
+ HitTestResult result = HitTestResult(pt);
+
+ if (contentRenderer())
+ result = eventHandler().hitTestResultAtPoint(pt, HitTestRequest::ReadOnly | HitTestRequest::Active);
+ return result.innerNode() ? &result.innerNode()->document() : 0;
}
-void LocalFrame::disconnectOwnerElement()
+PassRefPtrWillBeRawPtr<Range> LocalFrame::rangeForPoint(const IntPoint& framePoint)
{
- if (owner()) {
- if (Document* document = this->document())
- document->topDocument().clearAXObjectCache();
+ VisiblePosition position = visiblePositionForPoint(framePoint);
+ if (position.isNull())
+ return nullptr;
+
+ VisiblePosition previous = position.previous();
+ if (previous.isNotNull()) {
+ RefPtrWillBeRawPtr<Range> previousCharacterRange = makeRange(previous, position);
+ LayoutRect rect = editor().firstRectForRange(previousCharacterRange.get());
+ if (rect.contains(framePoint))
+ return previousCharacterRange.release();
+ }
+
+ VisiblePosition next = position.next();
+ if (RefPtrWillBeRawPtr<Range> nextCharacterRange = makeRange(position, next)) {
+ LayoutRect rect = editor().firstRectForRange(nextCharacterRange.get());
+ if (rect.contains(framePoint))
+ return nextCharacterRange.release();
+ }
+
+ return nullptr;
+}
+
+bool LocalFrame::isURLAllowed(const KURL& url) const
+{
+ // We allow one level of self-reference because some sites depend on that,
+ // but we don't allow more than one.
+ if (host()->subframeCount() >= FrameHost::maxNumberOfFrames)
+ return false;
+ bool foundSelfReference = false;
+ for (const Frame* frame = this; frame; frame = frame->tree().parent()) {
+ if (!frame->isLocalFrame())
+ continue;
+ if (equalIgnoringFragmentIdentifier(toLocalFrame(frame)->document()->url(), url)) {
+ if (foundSelfReference)
+ return false;
+ foundSelfReference = true;
+ }
+ }
+ return true;
+}
+
+bool LocalFrame::shouldReuseDefaultView(const KURL& url) const
+{
+ return loader().stateMachine()->isDisplayingInitialEmptyDocument() && document()->isSecureTransitionTo(url);
+}
+
+void LocalFrame::removeSpellingMarkersUnderWords(const Vector<String>& words)
+{
+ spellChecker().removeSpellingMarkersUnderWords(words);
+}
+
#if ENABLE(OILPAN)
- // Clear the FrameView and FrameLoader right here rather than
- // during finalization. Too late to access various heap objects
- // at that stage.
- setView(nullptr);
- loader().clear();
-#endif
+void LocalFrame::registerPluginElement(HTMLPlugInElement* plugin)
+{
+ m_pluginElements.add(plugin);
+}
+
+void LocalFrame::unregisterPluginElement(HTMLPlugInElement* plugin)
+{
+ ASSERT(m_pluginElements.contains(plugin));
+ m_pluginElements.remove(plugin);
+}
+
+void LocalFrame::clearWeakMembers(Visitor* visitor)
+{
+ Vector<HTMLPlugInElement*> deadPlugins;
+ for (const auto& pluginElement : m_pluginElements) {
+ if (!visitor->isAlive(pluginElement)) {
+ pluginElement->shouldDisposePlugin();
+ deadPlugins.append(pluginElement);
+ }
}
- Frame::disconnectOwnerElement();
+ for (unsigned i = 0; i < deadPlugins.size(); ++i)
+ m_pluginElements.remove(deadPlugins[i]);
}
+#endif
-LocalFrame* LocalFrame::localFrameRoot()
+String LocalFrame::localLayerTreeAsText(unsigned flags) const
{
- LocalFrame* curFrame = this;
- while (curFrame && curFrame->tree().parent() && curFrame->tree().parent()->isLocalFrame())
- curFrame = toLocalFrame(curFrame->tree().parent());
+ if (!contentRenderer())
+ return String();
- return curFrame;
+ return contentRenderer()->compositor()->layerTreeAsText(static_cast<LayerTreeFlags>(flags));
}
-void LocalFrame::setPagePopupOwner(Element& owner)
+inline LocalFrame::LocalFrame(FrameLoaderClient* client, FrameHost* host, FrameOwner* owner)
+ : Frame(client, host, owner)
+ , m_loader(this)
+ , m_navigationScheduler(this)
+ , m_script(ScriptController::create(this))
+ , m_editor(Editor::create(*this))
+ , m_spellChecker(SpellChecker::create(*this))
+ , m_selection(FrameSelection::create(this))
+ , m_eventHandler(adoptPtrWillBeNoop(new EventHandler(this)))
+ , m_console(FrameConsole::create(*this))
+ , m_inputMethodController(InputMethodController::create(*this))
+ , m_pageZoomFactor(parentPageZoomFactor(this))
+ , m_textZoomFactor(parentTextZoomFactor(this))
+ , m_inViewSourceMode(false)
{
- m_pagePopupOwner = &owner;
+}
+
+void LocalFrame::detachView()
+{
+ // We detach the FrameView's custom scroll bars as early as
+ // possible to prevent m_doc->detach() from messing with the view
+ // such that its scroll bars won't be torn down.
+ //
+ // FIXME: We should revisit this.
+ if (m_view)
+ m_view->prepareForDetach();
}
} // namespace blink