1/*
2 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
3 *                     1999 Lars Knoll <knoll@kde.org>
4 *                     1999 Antti Koivisto <koivisto@kde.org>
5 *                     2000 Simon Hausmann <hausmann@kde.org>
6 *                     2000 Stefan Schimanski <1Stein@gmx.de>
7 *                     2001 George Staikos <staikos@kde.org>
8 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
9 * Copyright (C) 2005 Alexey Proskuryakov <ap@nypop.com>
10 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
11 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
12 * Copyright (C) 2008 Google Inc.
13 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Library General Public
16 * License as published by the Free Software Foundation; either
17 * version 2 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22 * Library General Public License for more details.
23 *
24 * You should have received a copy of the GNU Library General Public License
25 * along with this library; see the file COPYING.LIB.  If not, write to
26 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
27 * Boston, MA 02110-1301, USA.
28 */
29
30#include "config.h"
31#include "core/frame/Frame.h"
32
33#include "core/dom/DocumentType.h"
34#include "core/events/Event.h"
35#include "core/frame/LocalDOMWindow.h"
36#include "core/frame/FrameHost.h"
37#include "core/frame/Settings.h"
38#include "core/html/HTMLFrameElementBase.h"
39#include "core/inspector/InspectorInstrumentation.h"
40#include "core/loader/EmptyClients.h"
41#include "core/loader/FrameLoaderClient.h"
42#include "core/page/Chrome.h"
43#include "core/page/ChromeClient.h"
44#include "core/page/EventHandler.h"
45#include "core/page/FocusController.h"
46#include "core/page/Page.h"
47#include "core/rendering/RenderLayer.h"
48#include "core/rendering/RenderPart.h"
49#include "platform/graphics/GraphicsLayer.h"
50#include "public/platform/WebLayer.h"
51#include "wtf/PassOwnPtr.h"
52#include "wtf/RefCountedLeakCounter.h"
53
54namespace blink {
55
56using namespace HTMLNames;
57
58DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, frameCounter, ("Frame"));
59
60Frame::Frame(FrameClient* client, FrameHost* host, FrameOwner* owner)
61    : m_treeNode(this)
62    , m_host(host)
63    , m_owner(owner)
64    , m_client(client)
65    , m_remotePlatformLayer(0)
66{
67    ASSERT(page());
68
69#ifndef NDEBUG
70    frameCounter.increment();
71#endif
72
73    if (m_owner) {
74        page()->incrementSubframeCount();
75        if (m_owner->isLocal())
76            toHTMLFrameOwnerElement(m_owner)->setContentFrame(*this);
77    } else {
78        page()->setMainFrame(this);
79    }
80}
81
82Frame::~Frame()
83{
84#if ENABLE(OILPAN)
85    ASSERT(!m_owner);
86#else
87    // FIXME: We should not be doing all this work inside the destructor
88    disconnectOwnerElement();
89    setDOMWindow(nullptr);
90#endif
91
92#ifndef NDEBUG
93    frameCounter.decrement();
94#endif
95}
96
97void Frame::trace(Visitor* visitor)
98{
99    visitor->trace(m_treeNode);
100    visitor->trace(m_host);
101    visitor->trace(m_owner);
102    visitor->trace(m_domWindow);
103}
104
105void Frame::detachChildren()
106{
107    typedef WillBeHeapVector<RefPtrWillBeMember<Frame> > FrameVector;
108    FrameVector childrenToDetach;
109    childrenToDetach.reserveCapacity(tree().childCount());
110    for (Frame* child = tree().firstChild(); child; child = child->tree().nextSibling())
111        childrenToDetach.append(child);
112    FrameVector::iterator end = childrenToDetach.end();
113    for (FrameVector::iterator it = childrenToDetach.begin(); it != end; ++it)
114        (*it)->detach();
115}
116
117FrameHost* Frame::host() const
118{
119    return m_host;
120}
121
122Page* Frame::page() const
123{
124    if (m_host)
125        return &m_host->page();
126    return 0;
127}
128
129Settings* Frame::settings() const
130{
131    if (m_host)
132        return &m_host->settings();
133    return 0;
134}
135
136void Frame::setDOMWindow(PassRefPtrWillBeRawPtr<LocalDOMWindow> domWindow)
137{
138    if (m_domWindow)
139        m_domWindow->reset();
140
141    m_domWindow = domWindow;
142}
143
144static ChromeClient& emptyChromeClient()
145{
146    DEFINE_STATIC_LOCAL(EmptyChromeClient, client, ());
147    return client;
148}
149
150ChromeClient& Frame::chromeClient() const
151{
152    if (Page* page = this->page())
153        return page->chrome().client();
154    return emptyChromeClient();
155}
156
157RenderPart* Frame::ownerRenderer() const
158{
159    if (!deprecatedLocalOwner())
160        return 0;
161    RenderObject* object = deprecatedLocalOwner()->renderer();
162    if (!object)
163        return 0;
164    // FIXME: If <object> is ever fixed to disassociate itself from frames
165    // that it has started but canceled, then this can turn into an ASSERT
166    // since ownerElement() would be 0 when the load is canceled.
167    // https://bugs.webkit.org/show_bug.cgi?id=18585
168    if (!object->isRenderPart())
169        return 0;
170    return toRenderPart(object);
171}
172
173void Frame::setRemotePlatformLayer(WebLayer* layer)
174{
175    if (m_remotePlatformLayer)
176        GraphicsLayer::unregisterContentsLayer(m_remotePlatformLayer);
177    m_remotePlatformLayer = layer;
178    if (m_remotePlatformLayer)
179        GraphicsLayer::registerContentsLayer(layer);
180
181    ASSERT(owner());
182    toHTMLFrameOwnerElement(owner())->setNeedsCompositingUpdate();
183    if (RenderPart* renderer = ownerRenderer())
184        renderer->layer()->updateSelfPaintingLayer();
185}
186
187bool Frame::isMainFrame() const
188{
189    Page* page = this->page();
190    return page && this == page->mainFrame();
191}
192
193bool Frame::isLocalRoot() const
194{
195    if (isRemoteFrame())
196        return false;
197
198    if (!tree().parent())
199        return true;
200
201    return tree().parent()->isRemoteFrame();
202}
203
204void Frame::disconnectOwnerElement()
205{
206    if (m_owner) {
207        if (m_owner->isLocal())
208            toHTMLFrameOwnerElement(m_owner)->clearContentFrame();
209        if (page())
210            page()->decrementSubframeCount();
211    }
212    m_owner = nullptr;
213}
214
215HTMLFrameOwnerElement* Frame::deprecatedLocalOwner() const
216{
217    return m_owner && m_owner->isLocal() ? toHTMLFrameOwnerElement(m_owner) : 0;
218}
219
220} // namespace blink
221