blob: 13ff081e60c73012c6b4e7455d56710726bd03c7 [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/exported/WebRemoteFrameImpl.h"
#include "bindings/core/v8/WindowProxy.h"
#include "core/dom/RemoteSecurityContext.h"
#include "core/dom/SecurityContext.h"
#include "core/exported/WebViewImpl.h"
#include "core/frame/LocalFrameView.h"
#include "core/frame/RemoteFrameClientImpl.h"
#include "core/frame/RemoteFrameOwner.h"
#include "core/frame/Settings.h"
#include "core/frame/WebLocalFrameImpl.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
#include "core/fullscreen/Fullscreen.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/layout/LayoutObject.h"
#include "core/layout/LayoutView.h"
#include "core/page/ChromeClient.h"
#include "core/page/Page.h"
#include "core/timing/DOMWindowPerformance.h"
#include "core/timing/Performance.h"
#include "platform/bindings/DOMWrapperWorld.h"
#include "platform/feature_policy/FeaturePolicy.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/LayoutRect.h"
#include "platform/heap/Handle.h"
#include "public/platform/WebFloatRect.h"
#include "public/platform/WebRect.h"
#include "public/platform/WebScrollIntoViewParams.h"
#include "public/web/WebDocument.h"
#include "public/web/WebFrameOwnerProperties.h"
#include "public/web/WebPerformance.h"
#include "public/web/WebRange.h"
#include "public/web/WebTreeScopeType.h"
#include "third_party/WebKit/common/feature_policy/feature_policy.h"
#include "v8/include/v8.h"
namespace blink {
WebRemoteFrame* WebRemoteFrame::Create(WebTreeScopeType scope,
WebRemoteFrameClient* client) {
return WebRemoteFrameImpl::Create(scope, client);
}
WebRemoteFrame* WebRemoteFrame::CreateMainFrame(WebView* web_view,
WebRemoteFrameClient* client,
WebFrame* opener) {
return WebRemoteFrameImpl::CreateMainFrame(web_view, client, opener);
}
WebRemoteFrameImpl* WebRemoteFrameImpl::Create(WebTreeScopeType scope,
WebRemoteFrameClient* client) {
WebRemoteFrameImpl* frame = new WebRemoteFrameImpl(scope, client);
return frame;
}
WebRemoteFrameImpl* WebRemoteFrameImpl::CreateMainFrame(
WebView* web_view,
WebRemoteFrameClient* client,
WebFrame* opener) {
WebRemoteFrameImpl* frame =
new WebRemoteFrameImpl(WebTreeScopeType::kDocument, client);
frame->SetOpener(opener);
Page& page = *static_cast<WebViewImpl*>(web_view)->GetPage();
// It would be nice to DCHECK that the main frame is not set yet here.
// Unfortunately, there is an edge case with a pending RenderFrameHost that
// violates this: the embedder may create a pending RenderFrameHost for
// navigating to a new page in a popup. If the navigation ends up redirecting
// to a site that requires a process swap, it doesn't go through the standard
// swapping path and instead directly overwrites the main frame.
// TODO(dcheng): Remove the need for this and strongly enforce this condition
// with a DCHECK.
frame->InitializeCoreFrame(page, nullptr, g_null_atom);
return frame;
}
WebRemoteFrameImpl::~WebRemoteFrameImpl() = default;
void WebRemoteFrameImpl::Trace(blink::Visitor* visitor) {
visitor->Trace(frame_client_);
visitor->Trace(frame_);
WebFrame::TraceFrames(visitor, this);
}
bool WebRemoteFrameImpl::IsWebLocalFrame() const {
return false;
}
WebLocalFrame* WebRemoteFrameImpl::ToWebLocalFrame() {
NOTREACHED();
return nullptr;
}
bool WebRemoteFrameImpl::IsWebRemoteFrame() const {
return true;
}
WebRemoteFrame* WebRemoteFrameImpl::ToWebRemoteFrame() {
return this;
}
void WebRemoteFrameImpl::Close() {
WebRemoteFrame::Close();
self_keep_alive_.Clear();
}
WebRect WebRemoteFrameImpl::VisibleContentRect() const {
NOTREACHED();
return WebRect();
}
WebView* WebRemoteFrameImpl::View() const {
if (!GetFrame()) {
return nullptr;
}
DCHECK(GetFrame()->GetPage());
return GetFrame()->GetPage()->GetChromeClient().GetWebView();
}
void WebRemoteFrameImpl::StopLoading() {
// TODO(dcheng,japhet): Calling this method should stop loads
// in all subframes, both remote and local.
}
WebLocalFrame* WebRemoteFrameImpl::CreateLocalChild(
WebTreeScopeType scope,
const WebString& name,
WebSandboxFlags sandbox_flags,
WebFrameClient* client,
blink::InterfaceRegistry* interface_registry,
WebFrame* previous_sibling,
const ParsedFeaturePolicy& container_policy,
const WebFrameOwnerProperties& frame_owner_properties,
WebFrame* opener) {
WebLocalFrameImpl* child =
WebLocalFrameImpl::Create(scope, client, interface_registry, opener);
InsertAfter(child, previous_sibling);
RemoteFrameOwner* owner =
RemoteFrameOwner::Create(static_cast<SandboxFlags>(sandbox_flags),
container_policy, frame_owner_properties);
child->InitializeCoreFrame(*GetFrame()->GetPage(), owner, name);
DCHECK(child->GetFrame());
return child;
}
void WebRemoteFrameImpl::InitializeCoreFrame(Page& page,
FrameOwner* owner,
const AtomicString& name) {
SetCoreFrame(RemoteFrame::Create(frame_client_.Get(), page, owner));
GetFrame()->CreateView();
frame_->Tree().SetName(name);
}
WebRemoteFrame* WebRemoteFrameImpl::CreateRemoteChild(
WebTreeScopeType scope,
const WebString& name,
WebSandboxFlags sandbox_flags,
const ParsedFeaturePolicy& container_policy,
WebRemoteFrameClient* client,
WebFrame* opener) {
WebRemoteFrameImpl* child = WebRemoteFrameImpl::Create(scope, client);
child->SetOpener(opener);
AppendChild(child);
RemoteFrameOwner* owner =
RemoteFrameOwner::Create(static_cast<SandboxFlags>(sandbox_flags),
container_policy, WebFrameOwnerProperties());
child->InitializeCoreFrame(*GetFrame()->GetPage(), owner, name);
return child;
}
void WebRemoteFrameImpl::SetWebLayer(WebLayer* layer) {
if (!GetFrame())
return;
GetFrame()->SetWebLayer(layer);
}
void WebRemoteFrameImpl::SetCoreFrame(RemoteFrame* frame) {
frame_ = frame;
}
WebRemoteFrameImpl* WebRemoteFrameImpl::FromFrame(RemoteFrame& frame) {
if (!frame.Client())
return nullptr;
RemoteFrameClientImpl* client =
static_cast<RemoteFrameClientImpl*>(frame.Client());
return client->GetWebFrame();
}
void WebRemoteFrameImpl::SetReplicatedOrigin(
const WebSecurityOrigin& origin,
bool is_potentially_trustworthy_unique_origin) {
DCHECK(GetFrame());
scoped_refptr<SecurityOrigin> security_origin = origin.Get()->IsolatedCopy();
security_origin->SetUniqueOriginIsPotentiallyTrustworthy(
is_potentially_trustworthy_unique_origin);
GetFrame()->GetSecurityContext()->SetReplicatedOrigin(security_origin);
// If the origin of a remote frame changed, the accessibility object for the
// owner element now points to a different child.
//
// TODO(dmazzoni, dcheng): there's probably a better way to solve this.
// Run SitePerProcessAccessibilityBrowserTest.TwoCrossSiteNavigations to
// ensure an alternate fix works. http://crbug.com/566222
FrameOwner* owner = GetFrame()->Owner();
if (owner && owner->IsLocal()) {
HTMLElement* owner_element = ToHTMLFrameOwnerElement(owner);
AXObjectCache* cache = owner_element->GetDocument().ExistingAXObjectCache();
if (cache)
cache->ChildrenChanged(owner_element);
}
}
void WebRemoteFrameImpl::SetReplicatedSandboxFlags(WebSandboxFlags flags) {
DCHECK(GetFrame());
GetFrame()->GetSecurityContext()->ResetSandboxFlags();
GetFrame()->GetSecurityContext()->EnforceSandboxFlags(
static_cast<SandboxFlags>(flags));
}
void WebRemoteFrameImpl::SetReplicatedName(const WebString& name) {
DCHECK(GetFrame());
GetFrame()->Tree().SetName(name);
}
void WebRemoteFrameImpl::SetReplicatedFeaturePolicyHeader(
const ParsedFeaturePolicy& parsed_header) {
if (RuntimeEnabledFeatures::FeaturePolicyEnabled()) {
FeaturePolicy* parent_feature_policy = nullptr;
if (Parent()) {
Frame* parent_frame = GetFrame()->Client()->Parent();
parent_feature_policy =
parent_frame->GetSecurityContext()->GetFeaturePolicy();
}
ParsedFeaturePolicy container_policy;
if (GetFrame()->Owner())
container_policy = GetFrame()->Owner()->ContainerPolicy();
GetFrame()->GetSecurityContext()->InitializeFeaturePolicy(
parsed_header, container_policy, parent_feature_policy);
}
}
void WebRemoteFrameImpl::AddReplicatedContentSecurityPolicyHeader(
const WebString& header_value,
WebContentSecurityPolicyType type,
WebContentSecurityPolicySource source) {
GetFrame()
->GetSecurityContext()
->GetContentSecurityPolicy()
->AddPolicyFromHeaderValue(
header_value, static_cast<ContentSecurityPolicyHeaderType>(type),
static_cast<ContentSecurityPolicyHeaderSource>(source));
}
void WebRemoteFrameImpl::ResetReplicatedContentSecurityPolicy() {
GetFrame()->GetSecurityContext()->ResetReplicatedContentSecurityPolicy();
}
void WebRemoteFrameImpl::SetReplicatedInsecureRequestPolicy(
WebInsecureRequestPolicy policy) {
DCHECK(GetFrame());
GetFrame()->GetSecurityContext()->SetInsecureRequestPolicy(policy);
}
void WebRemoteFrameImpl::SetReplicatedInsecureNavigationsSet(
const std::vector<unsigned>& set) {
DCHECK(GetFrame());
GetFrame()->GetSecurityContext()->SetInsecureNavigationsSet(set);
}
void WebRemoteFrameImpl::ForwardResourceTimingToParent(
const WebResourceTimingInfo& info) {
DCHECK(Parent()->IsWebLocalFrame());
WebLocalFrameImpl* parent_frame =
ToWebLocalFrameImpl(Parent()->ToWebLocalFrame());
HTMLFrameOwnerElement* owner_element =
ToHTMLFrameOwnerElement(frame_->Owner());
DOMWindowPerformance::performance(*parent_frame->GetFrame()->DomWindow())
->AddResourceTiming(info, owner_element->localName());
}
void WebRemoteFrameImpl::DispatchLoadEventForFrameOwner() {
DCHECK(GetFrame()->Owner()->IsLocal());
GetFrame()->Owner()->DispatchLoad();
}
void WebRemoteFrameImpl::DidStartLoading() {
GetFrame()->SetIsLoading(true);
}
void WebRemoteFrameImpl::DidStopLoading() {
GetFrame()->SetIsLoading(false);
if (Parent() && Parent()->IsWebLocalFrame()) {
WebLocalFrameImpl* parent_frame =
ToWebLocalFrameImpl(Parent()->ToWebLocalFrame());
parent_frame->GetFrame()->GetDocument()->CheckCompleted();
}
}
bool WebRemoteFrameImpl::IsIgnoredForHitTest() const {
HTMLFrameOwnerElement* owner = GetFrame()->DeprecatedLocalOwner();
if (!owner || !owner->GetLayoutObject())
return false;
return owner->GetLayoutObject()->Style()->PointerEvents() ==
EPointerEvents::kNone;
}
void WebRemoteFrameImpl::WillEnterFullscreen() {
// This should only ever be called when the FrameOwner is local.
HTMLFrameOwnerElement* owner_element =
ToHTMLFrameOwnerElement(GetFrame()->Owner());
// Call |requestFullscreen()| on |ownerElement| to make it the pending
// fullscreen element in anticipation of the coming |didEnterFullscreen()|
// call.
//
// PrefixedForCrossProcessDescendant is necessary because:
// - The fullscreen element ready check and other checks should be bypassed.
// - |ownerElement| will need :-webkit-full-screen-ancestor style in addition
// to :-webkit-full-screen.
//
// TODO(alexmos): currently, this assumes prefixed requests, but in the
// future, this should plumb in information about which request type
// (prefixed or unprefixed) to use for firing fullscreen events.
Fullscreen::RequestFullscreen(
*owner_element,
Fullscreen::RequestType::kPrefixedForCrossProcessDescendant);
}
void WebRemoteFrameImpl::SetHasReceivedUserGesture() {
GetFrame()->UpdateUserActivationInFrameTree();
}
void WebRemoteFrameImpl::ScrollRectToVisible(
const WebRect& rect_to_scroll,
const WebScrollIntoViewParams& params) {
Element* owner_element = frame_->DeprecatedLocalOwner();
LayoutObject* owner_object = owner_element->GetLayoutObject();
if (!owner_object) {
// The LayoutObject could be nullptr by the time we get here. For instance
// <iframe>'s style might have been set to 'display: none' right after
// scrolling starts in the OOPIF's process (see https://crbug.com/777811).
return;
}
// Schedule the scroll.
auto* scroll_sequencer =
owner_element->GetDocument().GetPage()->GetSmoothScrollSequencer();
scroll_sequencer->AbortAnimations();
LayoutRect new_rect_to_scroll = EnclosingLayoutRect(
owner_object
->LocalToAncestorQuad(FloatRect(rect_to_scroll), owner_object->View(),
kUseTransforms | kTraverseDocumentBoundaries)
.BoundingBox());
owner_object->EnclosingBox()->ScrollRectToVisibleRecursive(
LayoutRect(new_rect_to_scroll), params);
scroll_sequencer->RunQueuedAnimations();
}
void WebRemoteFrameImpl::SetHasReceivedUserGestureBeforeNavigation(bool value) {
GetFrame()->SetDocumentHasReceivedUserGestureBeforeNavigation(value);
}
v8::Local<v8::Object> WebRemoteFrameImpl::GlobalProxy() const {
return GetFrame()
->GetWindowProxy(DOMWrapperWorld::MainWorld())
->GlobalProxyIfNotDetached();
}
WebRemoteFrameImpl::WebRemoteFrameImpl(WebTreeScopeType scope,
WebRemoteFrameClient* client)
: WebRemoteFrame(scope),
frame_client_(RemoteFrameClientImpl::Create(this)),
client_(client),
self_keep_alive_(this) {
DCHECK(client);
}
} // namespace blink