Patch for https://bugs.webkit.org/show_bug.cgi?id=43305
[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 String WebFrame::innerText() const
189 {
190     if (!m_coreFrame)
191         return String();
192
193     return m_coreFrame->document()->documentElement()->innerText();
194 }
195
196 PassRefPtr<ImmutableArray> WebFrame::childFrames()
197 {
198     if (!m_coreFrame)
199         return ImmutableArray::create();
200
201     size_t size = m_coreFrame->tree()->childCount();
202     if (!size)
203         return ImmutableArray::create();
204
205     APIObject** array = new APIObject*[size];
206     unsigned i = 0;
207     for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling(), ++i) {
208         WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame();
209         webFrame->ref();
210         array[i] = webFrame;
211     }
212
213     return ImmutableArray::adopt(array, size);
214 }
215
216 unsigned WebFrame::numberOfActiveAnimations()
217 {
218     if (!m_coreFrame)
219         return 0;
220
221     AnimationController* controller = m_coreFrame->animation();
222     if (!controller)
223         return 0;
224
225     return controller->numberOfActiveAnimations();
226 }
227
228 bool WebFrame::pauseAnimationOnElementWithId(const String& animationName, const String& elementID, double time)
229 {
230     if (!m_coreFrame)
231         return false;
232
233     AnimationController* controller = m_coreFrame->animation();
234     if (!controller)
235         return false;
236
237     if (!m_coreFrame->document())
238         return false;
239
240     Node* coreNode = m_coreFrame->document()->getElementById(elementID);
241     if (!coreNode || !coreNode->renderer())
242         return false;
243
244     return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time);
245 }
246
247 JSGlobalContextRef WebFrame::jsContext()
248 {
249     // FIXME: Is there a way to get this and know that it's a JSGlobalContextRef?
250     // The const_cast here is a bit ugly.
251     return const_cast<JSGlobalContextRef>(toRef(m_coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec()));
252 }
253
254 JSValueRef WebFrame::computedStyleIncludingVisitedInfo(JSObjectRef element)
255 {
256     if (!m_coreFrame)
257         return 0;
258
259     JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(mainThreadNormalWorld());
260     ExecState* exec = globalObject->globalExec();
261
262     if (!toJS(element)->inherits(&JSElement::s_info))
263         return JSValueMakeUndefined(toRef(exec));
264
265     RefPtr<CSSComputedStyleDeclaration> style = computedStyle(static_cast<JSElement*>(toJS(element))->impl(), true);
266
267     JSLock lock(SilenceAssertionsOnly);
268     return toRef(exec, toJS(exec, globalObject, style.get()));
269 }
270
271 String WebFrame::counterValue(JSObjectRef element)
272 {
273     if (!toJS(element)->inherits(&JSElement::s_info))
274         return String();
275
276     return counterValueForElement(static_cast<JSElement*>(toJS(element))->impl());
277 }
278
279 String WebFrame::markerText(JSObjectRef element)
280 {
281     if (!toJS(element)->inherits(&JSElement::s_info))
282         return String();
283
284     return markerTextForListItem(static_cast<JSElement*>(toJS(element))->impl());
285 }
286
287 } // namespace WebKit