99a2504957696e2e9e97239a22fbea5c13575896
[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/Frame.h>
30 #include <WebCore/HTMLFrameOwnerElement.h>
31 #include <WebCore/PlatformString.h>
32
33 #ifndef NDEBUG
34 #include <wtf/RefCountedLeakCounter.h>
35 #endif
36
37 using namespace WebCore;
38
39 namespace WebKit {
40
41 #ifndef NDEBUG
42 static WTF::RefCountedLeakCounter webFrameCounter("WebFrame");
43 #endif
44
45 static uint64_t generateFrameID()
46 {
47     static uint64_t uniqueFrameID = 1;
48     return uniqueFrameID++;
49 }
50
51 static uint64_t generateListenerID()
52 {
53     static uint64_t uniqueListenerID = 1;
54     return uniqueListenerID++;
55 }
56
57 PassRefPtr<WebFrame> WebFrame::createMainFrame(WebPage* page)
58 {
59     return create(page, String(), 0);
60 }
61
62 PassRefPtr<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
63 {
64     return create(page, frameName, ownerElement);
65 }
66
67 PassRefPtr<WebFrame> WebFrame::create(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
68 {
69     RefPtr<WebFrame> frame = adoptRef(new WebFrame(page, frameName, ownerElement));
70     
71     // Add explict ref() that will be balanced in WebFrameLoaderClient::frameLoaderDestroyed().
72     frame->ref();
73     
74     return frame.release();
75 }
76
77 WebFrame::WebFrame(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
78     : m_page(page)
79     , m_coreFrame(0)
80     , m_policyListenerID(0)
81     , m_policyFunction(0)
82     , m_frameLoaderClient(this)
83     , m_frameID(generateFrameID())
84 {
85     m_page->addWebFrame(m_frameID, this);
86
87     RefPtr<Frame> frame = Frame::create(page->corePage(), ownerElement, &m_frameLoaderClient);
88     m_coreFrame = frame.get();
89
90     frame->tree()->setName(frameName);
91
92     if (ownerElement) {
93         ASSERT(ownerElement->document()->frame());
94         ownerElement->document()->frame()->tree()->appendChild(frame);
95     }
96
97     frame->init();
98
99 #ifndef NDEBUG
100     webFrameCounter.increment();
101 #endif
102 }
103
104 WebFrame::~WebFrame()
105 {
106     ASSERT(!m_coreFrame);
107
108 #ifndef NDEBUG
109     webFrameCounter.decrement();
110 #endif
111 }
112
113 void WebFrame::invalidate()
114 {
115     m_page->removeWebFrame(m_frameID);
116     m_coreFrame = 0;
117 }
118
119 uint64_t WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction policyFunction)
120 {
121     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
122
123     invalidatePolicyListener();
124
125     m_policyListenerID = generateListenerID();
126     m_policyFunction = policyFunction;
127     return m_policyListenerID;
128 }
129
130 void WebFrame::invalidatePolicyListener()
131 {
132     if (!m_policyListenerID)
133         return;
134
135     m_policyListenerID = 0;
136     m_policyFunction = 0;
137 }
138
139 void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action)
140 {
141     if (!m_coreFrame)
142         return;
143
144     if (!m_policyListenerID)
145         return;
146
147     if (listenerID != m_policyListenerID)
148         return;
149
150     ASSERT(m_policyFunction);
151
152     FramePolicyFunction function = m_policyFunction;
153
154     invalidatePolicyListener();
155
156     (m_coreFrame->loader()->policyChecker()->*function)(action);
157 }
158
159 bool WebFrame::isMainFrame() const
160 {
161     return m_page->mainFrame() == this;
162 }
163
164 String WebFrame::url() const
165 {
166     if (!m_coreFrame)
167         return String();
168
169     return m_coreFrame->loader()->url().string();
170 }
171
172 String WebFrame::innerText() const
173 {
174     if (!m_coreFrame)
175         return String();
176
177     return m_coreFrame->document()->documentElement()->innerText();
178 }
179
180 static void childFrameRef(const void* frame)
181 {
182     static_cast<WebFrame*>(const_cast<void*>(frame))->ref();
183 }
184
185 static void childFrameDeref(const void* frame)
186 {
187     static_cast<WebFrame*>(const_cast<void*>(frame))->deref();
188 }
189
190 PassRefPtr<ImmutableArray> WebFrame::childFrames()
191 {
192     if (!m_coreFrame)
193         return ImmutableArray::create();
194
195     size_t size = m_coreFrame->tree()->childCount();
196     if (!size)
197         return ImmutableArray::create();
198
199     void** array = new void*[size];
200     unsigned i = 0;
201     for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling(), ++i) {
202         WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame();
203         webFrame->ref();
204         array[i] = webFrame;
205     }
206
207     ImmutableArray::ImmutableArrayCallbacks callbacks = {
208         childFrameRef,
209         childFrameDeref
210     };
211     return ImmutableArray::adopt(array, size, &callbacks);
212 }
213
214 } // namespace WebKit