0c872c00ef40c5e99acffffd20632cdc47e36a38
[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 "InjectedBundleNodeHandle.h"
29 #include "InjectedBundleScriptWorld.h"
30 #include "WebPage.h"
31 #include <JavaScriptCore/APICast.h>
32 #include <JavaScriptCore/JSLock.h>
33 #include <WebCore/AnimationController.h>
34 #include <WebCore/CSSComputedStyleDeclaration.h>
35 #include <WebCore/Frame.h>
36 #include <WebCore/HTMLFrameOwnerElement.h>
37 #include <WebCore/JSCSSStyleDeclaration.h>
38 #include <WebCore/JSElement.h>
39 #include <WebCore/RenderTreeAsText.h>
40
41 #ifndef NDEBUG
42 #include <wtf/RefCountedLeakCounter.h>
43 #endif
44
45 using namespace JSC;
46 using namespace WebCore;
47
48 namespace WebKit {
49
50 #ifndef NDEBUG
51 static WTF::RefCountedLeakCounter webFrameCounter("WebFrame");
52 #endif
53
54 static uint64_t generateFrameID()
55 {
56     static uint64_t uniqueFrameID = 1;
57     return uniqueFrameID++;
58 }
59
60 static uint64_t generateListenerID()
61 {
62     static uint64_t uniqueListenerID = 1;
63     return uniqueListenerID++;
64 }
65
66 PassRefPtr<WebFrame> WebFrame::createMainFrame(WebPage* page)
67 {
68     return create(page, String(), 0);
69 }
70
71 PassRefPtr<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
72 {
73     return create(page, frameName, ownerElement);
74 }
75
76 PassRefPtr<WebFrame> WebFrame::create(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
77 {
78     RefPtr<WebFrame> frame = adoptRef(new WebFrame(page, frameName, ownerElement));
79     
80     // Add explict ref() that will be balanced in WebFrameLoaderClient::frameLoaderDestroyed().
81     frame->ref();
82     
83     return frame.release();
84 }
85
86 WebFrame::WebFrame(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
87     : m_page(page)
88     , m_coreFrame(0)
89     , m_policyListenerID(0)
90     , m_policyFunction(0)
91     , m_frameLoaderClient(this)
92     , m_loadListener(0)
93     , m_frameID(generateFrameID())
94 {
95     m_page->addWebFrame(m_frameID, this);
96
97     RefPtr<Frame> frame = Frame::create(page->corePage(), ownerElement, &m_frameLoaderClient);
98     m_coreFrame = frame.get();
99
100     frame->tree()->setName(frameName);
101
102     if (ownerElement) {
103         ASSERT(ownerElement->document()->frame());
104         ownerElement->document()->frame()->tree()->appendChild(frame);
105     }
106
107     frame->init();
108
109 #ifndef NDEBUG
110     webFrameCounter.increment();
111 #endif
112 }
113
114 WebFrame::~WebFrame()
115 {
116     ASSERT(!m_coreFrame);
117
118 #ifndef NDEBUG
119     webFrameCounter.decrement();
120 #endif
121 }
122
123 void WebFrame::invalidate()
124 {
125     m_page->removeWebFrame(m_frameID);
126     m_coreFrame = 0;
127 }
128
129 uint64_t WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction policyFunction)
130 {
131     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
132
133     invalidatePolicyListener();
134
135     m_policyListenerID = generateListenerID();
136     m_policyFunction = policyFunction;
137     return m_policyListenerID;
138 }
139
140 void WebFrame::invalidatePolicyListener()
141 {
142     if (!m_policyListenerID)
143         return;
144
145     m_policyListenerID = 0;
146     m_policyFunction = 0;
147 }
148
149 void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action)
150 {
151     if (!m_coreFrame)
152         return;
153
154     if (!m_policyListenerID)
155         return;
156
157     if (listenerID != m_policyListenerID)
158         return;
159
160     ASSERT(m_policyFunction);
161
162     FramePolicyFunction function = m_policyFunction;
163
164     invalidatePolicyListener();
165
166     (m_coreFrame->loader()->policyChecker()->*function)(action);
167 }
168
169 bool WebFrame::isMainFrame() const
170 {
171     return m_page->mainFrame() == this;
172 }
173
174 String WebFrame::name() const
175 {
176     if (!m_coreFrame)
177         return String();
178
179     return m_coreFrame->tree()->name();
180 }
181
182 String WebFrame::url() const
183 {
184     if (!m_coreFrame)
185         return String();
186
187     return m_coreFrame->loader()->url().string();
188 }
189
190 String WebFrame::innerText() const
191 {
192     if (!m_coreFrame)
193         return String();
194
195     if (!m_coreFrame->document()->documentElement())
196         return String();
197
198     return m_coreFrame->document()->documentElement()->innerText();
199 }
200
201 PassRefPtr<ImmutableArray> WebFrame::childFrames()
202 {
203     if (!m_coreFrame)
204         return ImmutableArray::create();
205
206     size_t size = m_coreFrame->tree()->childCount();
207     if (!size)
208         return ImmutableArray::create();
209
210     APIObject** array = new APIObject*[size];
211     unsigned i = 0;
212     for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling(), ++i) {
213         WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame();
214         webFrame->ref();
215         array[i] = webFrame;
216     }
217
218     return ImmutableArray::adopt(array, size);
219 }
220
221 unsigned WebFrame::numberOfActiveAnimations()
222 {
223     if (!m_coreFrame)
224         return 0;
225
226     AnimationController* controller = m_coreFrame->animation();
227     if (!controller)
228         return 0;
229
230     return controller->numberOfActiveAnimations();
231 }
232
233 bool WebFrame::pauseAnimationOnElementWithId(const String& animationName, const String& elementID, double time)
234 {
235     if (!m_coreFrame)
236         return false;
237
238     AnimationController* controller = m_coreFrame->animation();
239     if (!controller)
240         return false;
241
242     if (!m_coreFrame->document())
243         return false;
244
245     Node* coreNode = m_coreFrame->document()->getElementById(elementID);
246     if (!coreNode || !coreNode->renderer())
247         return false;
248
249     return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time);
250 }
251
252 unsigned WebFrame::pendingUnloadCount()
253 {
254     if (!m_coreFrame)
255         return 0;
256
257     return m_coreFrame->domWindow()->pendingUnloadEventListeners();
258 }
259
260 JSGlobalContextRef WebFrame::jsContext()
261 {
262     return toGlobalRef(m_coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
263 }
264
265 JSGlobalContextRef WebFrame::jsContextForWorld(InjectedBundleScriptWorld* world)
266 {
267     return toGlobalRef(m_coreFrame->script()->globalObject(world->coreWorld())->globalExec());
268 }
269
270 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world)
271 {
272     JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(world->coreWorld());
273     ExecState* exec = globalObject->globalExec();
274
275     JSLock lock(SilenceAssertionsOnly);
276     return toRef(exec, toJS(exec, globalObject, nodeHandle->coreNode()));
277 }
278
279 JSValueRef WebFrame::computedStyleIncludingVisitedInfo(JSObjectRef element)
280 {
281     if (!m_coreFrame)
282         return 0;
283
284     JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(mainThreadNormalWorld());
285     ExecState* exec = globalObject->globalExec();
286
287     if (!toJS(element)->inherits(&JSElement::s_info))
288         return JSValueMakeUndefined(toRef(exec));
289
290     RefPtr<CSSComputedStyleDeclaration> style = computedStyle(static_cast<JSElement*>(toJS(element))->impl(), true);
291
292     JSLock lock(SilenceAssertionsOnly);
293     return toRef(exec, toJS(exec, globalObject, style.get()));
294 }
295
296 String WebFrame::counterValue(JSObjectRef element)
297 {
298     if (!toJS(element)->inherits(&JSElement::s_info))
299         return String();
300
301     return counterValueForElement(static_cast<JSElement*>(toJS(element))->impl());
302 }
303
304 String WebFrame::markerText(JSObjectRef element)
305 {
306     if (!toJS(element)->inherits(&JSElement::s_info))
307         return String();
308
309     return markerTextForListItem(static_cast<JSElement*>(toJS(element))->impl());
310 }
311
312 } // namespace WebKit