2010-07-11 Maciej Stachowiak <mjs@apple.com>
[WebKit.git] / WebKit2 / WebProcess / WebPage / WebFrame.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "WebFrame.h"
27
28 #include "WebPage.h"
29 #include <WebCore/AnimationController.h>
30 #include <WebCore/Frame.h>
31 #include <WebCore/HTMLFrameOwnerElement.h>
32 #include <WebCore/PlatformString.h>
33
34 #ifndef NDEBUG
35 #include <wtf/RefCountedLeakCounter.h>
36 #endif
37
38 using namespace WebCore;
39
40 namespace WebKit {
41
42 #ifndef NDEBUG
43 static WTF::RefCountedLeakCounter webFrameCounter("WebFrame");
44 #endif
45
46 static uint64_t generateFrameID()
47 {
48     static uint64_t uniqueFrameID = 1;
49     return uniqueFrameID++;
50 }
51
52 static uint64_t generateListenerID()
53 {
54     static uint64_t uniqueListenerID = 1;
55     return uniqueListenerID++;
56 }
57
58 PassRefPtr<WebFrame> WebFrame::createMainFrame(WebPage* page)
59 {
60     return create(page, String(), 0);
61 }
62
63 PassRefPtr<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
64 {
65     return create(page, frameName, ownerElement);
66 }
67
68 PassRefPtr<WebFrame> WebFrame::create(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
69 {
70     RefPtr<WebFrame> frame = adoptRef(new WebFrame(page, frameName, ownerElement));
71     
72     // Add explict ref() that will be balanced in WebFrameLoaderClient::frameLoaderDestroyed().
73     frame->ref();
74     
75     return frame.release();
76 }
77
78 WebFrame::WebFrame(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
79     : m_page(page)
80     , m_coreFrame(0)
81     , m_policyListenerID(0)
82     , m_policyFunction(0)
83     , m_frameLoaderClient(this)
84     , m_frameID(generateFrameID())
85 {
86     m_page->addWebFrame(m_frameID, this);
87
88     RefPtr<Frame> frame = Frame::create(page->corePage(), ownerElement, &m_frameLoaderClient);
89     m_coreFrame = frame.get();
90
91     frame->tree()->setName(frameName);
92
93     if (ownerElement) {
94         ASSERT(ownerElement->document()->frame());
95         ownerElement->document()->frame()->tree()->appendChild(frame);
96     }
97
98     frame->init();
99
100 #ifndef NDEBUG
101     webFrameCounter.increment();
102 #endif
103 }
104
105 WebFrame::~WebFrame()
106 {
107     ASSERT(!m_coreFrame);
108
109 #ifndef NDEBUG
110     webFrameCounter.decrement();
111 #endif
112 }
113
114 void WebFrame::invalidate()
115 {
116     m_page->removeWebFrame(m_frameID);
117     m_coreFrame = 0;
118 }
119
120 uint64_t WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction policyFunction)
121 {
122     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
123
124     invalidatePolicyListener();
125
126     m_policyListenerID = generateListenerID();
127     m_policyFunction = policyFunction;
128     return m_policyListenerID;
129 }
130
131 void WebFrame::invalidatePolicyListener()
132 {
133     if (!m_policyListenerID)
134         return;
135
136     m_policyListenerID = 0;
137     m_policyFunction = 0;
138 }
139
140 void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action)
141 {
142     if (!m_coreFrame)
143         return;
144
145     if (!m_policyListenerID)
146         return;
147
148     if (listenerID != m_policyListenerID)
149         return;
150
151     ASSERT(m_policyFunction);
152
153     FramePolicyFunction function = m_policyFunction;
154
155     invalidatePolicyListener();
156
157     (m_coreFrame->loader()->policyChecker()->*function)(action);
158 }
159
160 bool WebFrame::isMainFrame() const
161 {
162     return m_page->mainFrame() == this;
163 }
164
165 String WebFrame::url() const
166 {
167     if (!m_coreFrame)
168         return String();
169
170     return m_coreFrame->loader()->url().string();
171 }
172
173 String WebFrame::innerText() const
174 {
175     if (!m_coreFrame)
176         return String();
177
178     return m_coreFrame->document()->documentElement()->innerText();
179 }
180
181 static void childFrameRef(const void* frame)
182 {
183     static_cast<WebFrame*>(const_cast<void*>(frame))->ref();
184 }
185
186 static void childFrameDeref(const void* frame)
187 {
188     static_cast<WebFrame*>(const_cast<void*>(frame))->deref();
189 }
190
191 PassRefPtr<ImmutableArray> WebFrame::childFrames()
192 {
193     if (!m_coreFrame)
194         return ImmutableArray::create();
195
196     size_t size = m_coreFrame->tree()->childCount();
197     if (!size)
198         return ImmutableArray::create();
199
200     void** array = new void*[size];
201     unsigned i = 0;
202     for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling(), ++i) {
203         WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame();
204         webFrame->ref();
205         array[i] = webFrame;
206     }
207
208     ImmutableArray::ImmutableArrayCallbacks callbacks = {
209         childFrameRef,
210         childFrameDeref
211     };
212     return ImmutableArray::adopt(array, size, &callbacks);
213 }
214
215 unsigned WebFrame::numberOfActiveAnimations()
216 {
217     if (!m_coreFrame)
218         return 0;
219
220     AnimationController* controller = m_coreFrame->animation();
221     if (!controller)
222         return 0;
223
224     return controller->numberOfActiveAnimations();
225 }
226
227 bool WebFrame::pauseAnimationOnElementWithId(const String& animationName, const String& elementID, double time)
228 {
229     if (!m_coreFrame)
230         return false;
231
232     AnimationController* controller = m_coreFrame->animation();
233     if (!controller)
234         return false;
235
236     if (!m_coreFrame->document())
237         return false;
238
239     Node* coreNode = m_coreFrame->document()->getElementById(elementID);
240     if (!coreNode || !coreNode->renderer())
241         return false;
242
243     return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time);
244 }
245
246
247 } // namespace WebKit