blob: 8c48a72d141ac9a5aebc78833356e1aa3e59620b [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/frame/RemoteFrameView.h"
#include "core/dom/IntersectionObserverEntry.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/RemoteFrame.h"
#include "core/frame/RemoteFrameClient.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/layout/LayoutView.h"
#include "core/layout/api/LayoutPartItem.h"
namespace blink {
RemoteFrameView::RemoteFrameView(RemoteFrame* remoteFrame)
: m_remoteFrame(remoteFrame) {
ASSERT(remoteFrame);
}
RemoteFrameView::~RemoteFrameView() {}
void RemoteFrameView::setParent(FrameViewBase* parent) {
FrameViewBase::setParent(parent);
frameRectsChanged();
}
RemoteFrameView* RemoteFrameView::create(RemoteFrame* remoteFrame) {
RemoteFrameView* view = new RemoteFrameView(remoteFrame);
view->show();
return view;
}
void RemoteFrameView::updateRemoteViewportIntersection() {
if (!m_remoteFrame->ownerLayoutObject())
return;
FrameView* localRootView =
toLocalFrame(m_remoteFrame->tree().parent())->localFrameRoot()->view();
if (!localRootView)
return;
// Start with rect in remote frame's coordinate space. Then
// mapToVisualRectInAncestorSpace will move it to the local root's coordinate
// space and account for any clip from containing elements such as a
// scrollable div. Passing nullptr as an argument to
// mapToVisualRectInAncestorSpace causes it to be clipped to the viewport,
// even if there are RemoteFrame ancestors in the frame tree.
LayoutRect rect(0, 0, frameRect().width(), frameRect().height());
rect.move(m_remoteFrame->ownerLayoutObject()->contentBoxOffset());
if (!m_remoteFrame->ownerLayoutObject()->mapToVisualRectInAncestorSpace(
nullptr, rect))
return;
IntRect rootVisibleRect = localRootView->visibleContentRect();
IntRect viewportIntersection(rect);
viewportIntersection.intersect(rootVisibleRect);
viewportIntersection.move(-localRootView->scrollOffsetInt());
// Translate the intersection rect from the root frame's coordinate space
// to the remote frame's coordinate space.
viewportIntersection = convertFromRootFrame(viewportIntersection);
if (viewportIntersection != m_lastViewportIntersection) {
m_remoteFrame->client()->updateRemoteViewportIntersection(
viewportIntersection);
}
m_lastViewportIntersection = viewportIntersection;
}
void RemoteFrameView::dispose() {
HTMLFrameOwnerElement* ownerElement = m_remoteFrame->deprecatedLocalOwner();
// ownerElement can be null during frame swaps, because the
// RemoteFrameView is disconnected before detachment.
if (ownerElement && ownerElement->ownedWidget() == this)
ownerElement->setWidget(nullptr);
FrameViewBase::dispose();
}
void RemoteFrameView::invalidateRect(const IntRect& rect) {
LayoutPartItem layoutItem = m_remoteFrame->ownerLayoutItem();
if (layoutItem.isNull())
return;
LayoutRect repaintRect(rect);
repaintRect.move(layoutItem.borderLeft() + layoutItem.paddingLeft(),
layoutItem.borderTop() + layoutItem.paddingTop());
layoutItem.invalidatePaintRectangle(repaintRect);
}
void RemoteFrameView::setFrameRect(const IntRect& newRect) {
IntRect oldRect = frameRect();
if (newRect == oldRect)
return;
FrameViewBase::setFrameRect(newRect);
frameRectsChanged();
}
void RemoteFrameView::frameRectsChanged() {
// Update the rect to reflect the position of the frame relative to the
// containing local frame root. The position of the local root within
// any remote frames, if any, is accounted for by the embedder.
IntRect newRect = frameRect();
if (parent() && parent()->isFrameView())
newRect = parent()->convertToRootFrame(
toFrameView(parent())->contentsToFrame(newRect));
m_remoteFrame->client()->frameRectsChanged(newRect);
updateRemoteViewportIntersection();
}
void RemoteFrameView::hide() {
setSelfVisible(false);
FrameViewBase::hide();
m_remoteFrame->client()->visibilityChanged(false);
}
void RemoteFrameView::show() {
setSelfVisible(true);
FrameViewBase::show();
m_remoteFrame->client()->visibilityChanged(true);
}
void RemoteFrameView::setParentVisible(bool visible) {
if (isParentVisible() == visible)
return;
FrameViewBase::setParentVisible(visible);
if (!isSelfVisible())
return;
m_remoteFrame->client()->visibilityChanged(isVisible());
}
DEFINE_TRACE(RemoteFrameView) {
visitor->trace(m_remoteFrame);
FrameViewBase::trace(visitor);
}
} // namespace blink