blob: 9299387f5d52a78c02249d452282595528311661 [file] [log] [blame]
/*
* Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
* 1999 Lars Knoll <knoll@kde.org>
* 1999 Antti Koivisto <koivisto@kde.org>
* 2000 Simon Hausmann <hausmann@kde.org>
* 2000 Stefan Schimanski <1Stein@gmx.de>
* 2001 George Staikos <staikos@kde.org>
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
* rights reserved.
* Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
* Copyright (C) 2008 Eric Seidel <eric@webkit.org>
* Copyright (C) 2008 Google Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "core/frame/Frame.h"
#include "bindings/core/v8/WindowProxyManager.h"
#include "core/dom/DocumentType.h"
#include "core/dom/UserGestureIndicator.h"
#include "core/events/Event.h"
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/Settings.h"
#include "core/frame/UseCounter.h"
#include "core/html/HTMLFrameElementBase.h"
#include "core/input/EventHandler.h"
#include "core/layout/LayoutPart.h"
#include "core/layout/api/LayoutPartItem.h"
#include "core/loader/EmptyClients.h"
#include "core/loader/NavigationScheduler.h"
#include "core/page/FocusController.h"
#include "core/page/Page.h"
#include "core/probe/CoreProbes.h"
#include "platform/InstanceCounters.h"
#include "platform/feature_policy/FeaturePolicy.h"
#include "platform/loader/fetch/ResourceError.h"
namespace blink {
using namespace HTMLNames;
Frame::~Frame() {
InstanceCounters::DecrementCounter(InstanceCounters::kFrameCounter);
DCHECK(!owner_);
DCHECK_EQ(lifecycle_.GetState(), FrameLifecycle::kDetached);
}
DEFINE_TRACE(Frame) {
visitor->Trace(tree_node_);
visitor->Trace(page_);
visitor->Trace(owner_);
visitor->Trace(window_proxy_manager_);
visitor->Trace(dom_window_);
visitor->Trace(client_);
}
void Frame::Detach(FrameDetachType type) {
DCHECK(client_);
// By the time this method is called, the subclasses should have already
// advanced to the Detaching state.
DCHECK_EQ(lifecycle_.GetState(), FrameLifecycle::kDetaching);
client_->SetOpener(0);
// After this, we must no longer talk to the client since this clears
// its owning reference back to our owning LocalFrame.
client_->Detached(type);
client_ = nullptr;
// TODO(dcheng): This currently needs to happen after calling
// FrameClient::Detached() to make it easier for FrameClient::Detached()
// implementations to detect provisional frames and avoid removing them from
// the frame tree. https://crbug.com/578349.
DisconnectOwnerElement();
page_ = nullptr;
}
void Frame::DisconnectOwnerElement() {
if (owner_) {
// Ocassionally, provisional frames need to be detached, but it shouldn't
// affect the frame tree structure. Make sure the frame owner's content
// frame actually refers to this frame before clearing it.
// TODO(dcheng): https://crbug.com/578349 tracks the cleanup for this once
// it's no longer needed.
if (owner_->ContentFrame() == this)
owner_->ClearContentFrame();
owner_ = nullptr;
}
}
Page* Frame::GetPage() const {
return page_;
}
bool Frame::IsMainFrame() const {
return !Tree().Parent();
}
bool Frame::IsLocalRoot() const {
if (IsRemoteFrame())
return false;
if (!Tree().Parent())
return true;
return Tree().Parent()->IsRemoteFrame();
}
HTMLFrameOwnerElement* Frame::DeprecatedLocalOwner() const {
return owner_ && owner_->IsLocal() ? ToHTMLFrameOwnerElement(owner_)
: nullptr;
}
static ChromeClient& GetEmptyChromeClient() {
DEFINE_STATIC_LOCAL(EmptyChromeClient, client, (EmptyChromeClient::Create()));
return client;
}
ChromeClient& Frame::GetChromeClient() const {
if (Page* page = this->GetPage())
return page->GetChromeClient();
return GetEmptyChromeClient();
}
Frame* Frame::FindUnsafeParentScrollPropagationBoundary() {
Frame* current_frame = this;
Frame* ancestor_frame = Tree().Parent();
while (ancestor_frame) {
if (!ancestor_frame->GetSecurityContext()->GetSecurityOrigin()->CanAccess(
GetSecurityContext()->GetSecurityOrigin()))
return current_frame;
current_frame = ancestor_frame;
ancestor_frame = ancestor_frame->Tree().Parent();
}
return nullptr;
}
LayoutPart* Frame::OwnerLayoutObject() const {
if (!DeprecatedLocalOwner())
return nullptr;
LayoutObject* object = DeprecatedLocalOwner()->GetLayoutObject();
if (!object)
return nullptr;
// FIXME: If <object> is ever fixed to disassociate itself from frames
// that it has started but canceled, then this can turn into an ASSERT
// since ownerElement() would be 0 when the load is canceled.
// https://bugs.webkit.org/show_bug.cgi?id=18585
if (!object->IsLayoutPart())
return nullptr;
return ToLayoutPart(object);
}
LayoutPartItem Frame::OwnerLayoutItem() const {
return LayoutPartItem(OwnerLayoutObject());
}
Settings* Frame::GetSettings() const {
if (GetPage())
return &GetPage()->GetSettings();
return nullptr;
}
WindowProxy* Frame::GetWindowProxy(DOMWrapperWorld& world) {
return window_proxy_manager_->GetWindowProxy(world);
}
void Frame::DidChangeVisibilityState() {
HeapVector<Member<Frame>> child_frames;
for (Frame* child = Tree().FirstChild(); child;
child = child->Tree().NextSibling())
child_frames.push_back(child);
for (size_t i = 0; i < child_frames.size(); ++i)
child_frames[i]->DidChangeVisibilityState();
}
void Frame::SetDocumentHasReceivedUserGesture() {
has_received_user_gesture_ = true;
if (Frame* parent = Tree().Parent())
parent->SetDocumentHasReceivedUserGesture();
}
bool Frame::IsFeatureEnabled(WebFeaturePolicyFeature feature) const {
WebFeaturePolicy* feature_policy = GetSecurityContext()->GetFeaturePolicy();
// The policy should always be initialized before checking it to ensure we
// properly inherit the parent policy.
DCHECK(feature_policy);
// Otherwise, check policy.
return feature_policy->IsFeatureEnabled(feature);
}
Frame::Frame(FrameClient* client,
Page& page,
FrameOwner* owner,
WindowProxyManager* window_proxy_manager)
: tree_node_(this),
page_(&page),
owner_(owner),
client_(client),
window_proxy_manager_(window_proxy_manager),
is_loading_(false) {
InstanceCounters::IncrementCounter(InstanceCounters::kFrameCounter);
if (owner_)
owner_->SetContentFrame(*this);
else
page_->SetMainFrame(this);
}
} // namespace blink