blob: eb10da425f3f7156dba1ac1c005d2cedb5379320 [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/RemoteFrame.h"
#include "bindings/core/v8/WindowProxy.h"
#include "bindings/core/v8/WindowProxyManager.h"
#include "core/dom/RemoteSecurityContext.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/RemoteDOMWindow.h"
#include "core/frame/RemoteFrameClient.h"
#include "core/frame/RemoteFrameView.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/layout/api/LayoutPartItem.h"
#include "core/loader/FrameLoadRequest.h"
#include "core/loader/FrameLoader.h"
#include "core/paint/PaintLayer.h"
#include "platform/PluginScriptForbiddenScope.h"
#include "platform/UserGestureIndicator.h"
#include "platform/graphics/GraphicsLayer.h"
#include "platform/network/ResourceRequest.h"
#include "platform/weborigin/SecurityPolicy.h"
#include "public/platform/WebLayer.h"
namespace blink {
inline RemoteFrame::RemoteFrame(RemoteFrameClient* client,
FrameHost* host,
FrameOwner* owner)
: Frame(client, host, owner),
m_view(nullptr),
m_securityContext(RemoteSecurityContext::create()),
m_domWindow(RemoteDOMWindow::create(*this)),
m_windowProxyManager(WindowProxyManager::create(*this)),
m_remotePlatformLayer(nullptr) {}
RemoteFrame* RemoteFrame::create(RemoteFrameClient* client,
FrameHost* host,
FrameOwner* owner) {
return new RemoteFrame(client, host, owner);
}
RemoteFrame::~RemoteFrame() {
ASSERT(!m_view);
}
DEFINE_TRACE(RemoteFrame) {
visitor->trace(m_view);
visitor->trace(m_securityContext);
visitor->trace(m_domWindow);
visitor->trace(m_windowProxyManager);
Frame::trace(visitor);
}
DOMWindow* RemoteFrame::domWindow() const {
return m_domWindow.get();
}
WindowProxy* RemoteFrame::windowProxy(DOMWrapperWorld& world) {
WindowProxy* windowProxy = m_windowProxyManager->windowProxy(world);
ASSERT(windowProxy);
windowProxy->initializeIfNeeded();
return windowProxy;
}
void RemoteFrame::navigate(Document& originDocument,
const KURL& url,
bool replaceCurrentItem,
UserGestureStatus userGestureStatus) {
FrameLoadRequest frameRequest(&originDocument, url);
frameRequest.setReplacesCurrentItem(replaceCurrentItem);
frameRequest.resourceRequest().setHasUserGesture(userGestureStatus ==
UserGestureStatus::Active);
navigate(frameRequest);
}
void RemoteFrame::navigate(const FrameLoadRequest& passedRequest) {
FrameLoadRequest frameRequest(passedRequest);
// The process where this frame actually lives won't have sufficient
// information to determine correct referrer, since it won't have access to
// the originDocument. Set it now.
FrameLoader::setReferrerForFrameRequest(frameRequest);
frameRequest.resourceRequest().setHasUserGesture(
UserGestureIndicator::processingUserGesture());
client()->navigate(frameRequest.resourceRequest(),
frameRequest.replacesCurrentItem());
}
void RemoteFrame::reload(FrameLoadType frameLoadType,
ClientRedirectPolicy clientRedirectPolicy) {
client()->reload(frameLoadType, clientRedirectPolicy);
}
void RemoteFrame::detach(FrameDetachType type) {
PluginScriptForbiddenScope forbidPluginDestructorScripting;
detachChildren();
if (!client())
return;
// Clean up the frame's view if needed. A remote frame only has a view if
// the parent is a local frame.
if (m_view)
m_view->dispose();
client()->willBeDetached();
m_windowProxyManager->clearForClose();
setView(nullptr);
if (m_remotePlatformLayer)
setRemotePlatformLayer(nullptr);
Frame::detach(type);
}
bool RemoteFrame::prepareForCommit() {
detachChildren();
return !!host();
}
RemoteSecurityContext* RemoteFrame::securityContext() const {
return m_securityContext.get();
}
bool RemoteFrame::shouldClose() {
// TODO(nasko): Implement running the beforeunload handler in the actual
// LocalFrame running in a different process and getting back a real result.
return true;
}
void RemoteFrame::forwardInputEvent(Event* event) {
client()->forwardInputEvent(event);
}
void RemoteFrame::frameRectsChanged(const IntRect& frameRect) {
client()->frameRectsChanged(frameRect);
}
void RemoteFrame::visibilityChanged(bool visible) {
if (client())
client()->visibilityChanged(visible);
}
void RemoteFrame::setView(RemoteFrameView* view) {
// Oilpan: as RemoteFrameView performs no finalization actions,
// no explicit dispose() of it needed here. (cf. FrameView::dispose().)
m_view = view;
// ... the RemoteDOMWindow will need to be informed of detachment,
// as otherwise it will keep a strong reference back to this RemoteFrame.
// That combined with wrappers (owned and kept alive by RemoteFrame) keeping
// persistent strong references to RemoteDOMWindow will prevent the GCing
// of all these objects. Break the cycle by notifying of detachment.
if (!m_view)
m_domWindow->frameDetached();
}
void RemoteFrame::createView() {
// If the RemoteFrame does not have a LocalFrame parent, there's no need to
// create a widget for it.
if (!deprecatedLocalOwner())
return;
ASSERT(!deprecatedLocalOwner()->ownedWidget());
setView(RemoteFrameView::create(this));
if (!ownerLayoutItem().isNull())
deprecatedLocalOwner()->setWidget(m_view);
}
RemoteFrameClient* RemoteFrame::client() const {
return static_cast<RemoteFrameClient*>(Frame::client());
}
void RemoteFrame::setRemotePlatformLayer(WebLayer* layer) {
if (m_remotePlatformLayer)
GraphicsLayer::unregisterContentsLayer(m_remotePlatformLayer);
m_remotePlatformLayer = layer;
if (m_remotePlatformLayer)
GraphicsLayer::registerContentsLayer(layer);
ASSERT(owner());
toHTMLFrameOwnerElement(owner())->setNeedsCompositingUpdate();
}
void RemoteFrame::advanceFocus(WebFocusType type, LocalFrame* source) {
client()->advanceFocus(type, source);
}
void RemoteFrame::detachChildren() {
using FrameVector = HeapVector<Member<Frame>>;
FrameVector childrenToDetach;
childrenToDetach.reserveCapacity(tree().childCount());
for (Frame* child = tree().firstChild(); child;
child = child->tree().nextSibling())
childrenToDetach.append(child);
for (const auto& child : childrenToDetach)
child->detach(FrameDetachType::Remove);
}
} // namespace blink