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