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 "config.h"
27 #include "WebFrameProxy.h"
28
29 #include "WebCertificateInfo.h"
30 #include "WebContext.h"
31 #include "WebFormSubmissionListenerProxy.h"
32 #include "WebFramePolicyListenerProxy.h"
33 #include "WebPageMessages.h"
34 #include "WebPageProxy.h"
35 #include <WebCore/DOMImplementation.h>
36 #include <WebCore/Image.h>
37 #include <wtf/text/WTFString.h>
38
39 using namespace WebCore;
40 using namespace std;
41
42 namespace WebKit {
43
WebFrameProxy(WebPageProxy * page,uint64_t frameID)44 WebFrameProxy::WebFrameProxy(WebPageProxy* page, uint64_t frameID)
45 : m_page(page)
46 , m_parentFrame(0)
47 , m_nextSibling(0)
48 , m_previousSibling(0)
49 , m_firstChild(0)
50 , m_lastChild(0)
51 , m_loadState(LoadStateFinished)
52 , m_isFrameSet(false)
53 , m_frameID(frameID)
54 {
55 WebContext::statistics().wkFrameCount++;
56 }
57
~WebFrameProxy()58 WebFrameProxy::~WebFrameProxy()
59 {
60 WebContext::statistics().wkFrameCount--;
61 }
62
disconnect()63 void WebFrameProxy::disconnect()
64 {
65 m_page = 0;
66 m_parentFrame = 0;
67 m_nextSibling = 0;
68 m_previousSibling = 0;
69 m_firstChild = 0;
70 m_lastChild = 0;
71
72 if (m_activeListener) {
73 m_activeListener->invalidate();
74 m_activeListener = 0;
75 }
76 }
77
isMainFrame() const78 bool WebFrameProxy::isMainFrame() const
79 {
80 if (!m_page)
81 return false;
82
83 return this == m_page->mainFrame();
84 }
85
stopLoading() const86 void WebFrameProxy::stopLoading() const
87 {
88 if (!m_page)
89 return;
90
91 if (!m_page->isValid())
92 return;
93
94 m_page->process()->send(Messages::WebPage::StopLoadingFrame(m_frameID), m_page->pageID());
95 }
96
canProvideSource() const97 bool WebFrameProxy::canProvideSource() const
98 {
99 return isDisplayingMarkupDocument();
100 }
101
canShowMIMEType(const String & mimeType) const102 bool WebFrameProxy::canShowMIMEType(const String& mimeType) const
103 {
104 if (!m_page)
105 return false;
106
107 if (m_page->canShowMIMEType(mimeType))
108 return true;
109
110 #if PLATFORM(MAC)
111 // On Mac, we can show PDFs in the main frame.
112 if (isMainFrame() && !mimeType.isEmpty())
113 return WebContext::pdfAndPostScriptMIMETypes().contains(mimeType);
114 #endif
115
116 return false;
117 }
118
isDisplayingStandaloneImageDocument() const119 bool WebFrameProxy::isDisplayingStandaloneImageDocument() const
120 {
121 return Image::supportsType(m_MIMEType);
122 }
123
isDisplayingMarkupDocument() const124 bool WebFrameProxy::isDisplayingMarkupDocument() const
125 {
126 // FIXME: This check should be moved to somewhere in WebCore.
127 // FIXME: This returns false when displaying a web archive.
128 return m_MIMEType == "text/html" || m_MIMEType == "image/svg+xml" || DOMImplementation::isXMLMIMEType(m_MIMEType);
129 }
130
didStartProvisionalLoad(const String & url)131 void WebFrameProxy::didStartProvisionalLoad(const String& url)
132 {
133 ASSERT(m_loadState == LoadStateFinished);
134 ASSERT(m_provisionalURL.isEmpty());
135 m_loadState = LoadStateProvisional;
136 m_provisionalURL = url;
137 }
138
didReceiveServerRedirectForProvisionalLoad(const String & url)139 void WebFrameProxy::didReceiveServerRedirectForProvisionalLoad(const String& url)
140 {
141 ASSERT(m_loadState == LoadStateProvisional);
142 m_provisionalURL = url;
143 }
144
didFailProvisionalLoad()145 void WebFrameProxy::didFailProvisionalLoad()
146 {
147 ASSERT(m_loadState == LoadStateProvisional);
148 m_loadState = LoadStateFinished;
149 m_provisionalURL = String();
150 }
151
didCommitLoad(const String & contentType,const PlatformCertificateInfo & certificateInfo)152 void WebFrameProxy::didCommitLoad(const String& contentType, const PlatformCertificateInfo& certificateInfo)
153 {
154 ASSERT(m_loadState == LoadStateProvisional);
155 m_loadState = LoadStateCommitted;
156 m_url = m_provisionalURL;
157 m_provisionalURL = String();
158 m_title = String();
159 m_MIMEType = contentType;
160 m_isFrameSet = false;
161 m_certificateInfo = WebCertificateInfo::create(certificateInfo);
162 }
163
didFinishLoad()164 void WebFrameProxy::didFinishLoad()
165 {
166 ASSERT(m_loadState == LoadStateCommitted);
167 ASSERT(m_provisionalURL.isEmpty());
168 m_loadState = LoadStateFinished;
169 }
170
didFailLoad()171 void WebFrameProxy::didFailLoad()
172 {
173 ASSERT(m_loadState == LoadStateCommitted);
174 ASSERT(m_provisionalURL.isEmpty());
175 m_loadState = LoadStateFinished;
176 m_title = String();
177 }
178
didSameDocumentNavigation(const String & url)179 void WebFrameProxy::didSameDocumentNavigation(const String& url)
180 {
181 m_url = url;
182 }
183
didChangeTitle(const String & title)184 void WebFrameProxy::didChangeTitle(const String& title)
185 {
186 m_title = title;
187 }
188
appendChild(WebFrameProxy * child)189 void WebFrameProxy::appendChild(WebFrameProxy* child)
190 {
191 ASSERT(child->page() == page());
192 ASSERT(!child->m_parentFrame);
193 ASSERT(!child->m_nextSibling);
194 ASSERT(!child->m_previousSibling);
195
196 child->m_parentFrame = this;
197
198 WebFrameProxy* oldLast = m_lastChild;
199 m_lastChild = child;
200
201 if (oldLast) {
202 ASSERT(!oldLast->m_nextSibling);
203 child->m_previousSibling = oldLast;
204 oldLast->m_nextSibling = child;
205 } else
206 m_firstChild = child;
207 }
208
removeChild(WebFrameProxy * child)209 void WebFrameProxy::removeChild(WebFrameProxy* child)
210 {
211 child->m_parentFrame = 0;
212
213 WebFrameProxy*& newLocationForNext = m_firstChild == child ? m_firstChild : child->m_previousSibling->m_nextSibling;
214 WebFrameProxy*& newLocationForPrevious = m_lastChild == child ? m_lastChild : child->m_nextSibling->m_previousSibling;
215 swap(newLocationForNext, child->m_nextSibling);
216 swap(newLocationForPrevious, child->m_previousSibling);
217 child->m_previousSibling = 0;
218 child->m_nextSibling = 0;
219 }
220
isDescendantOf(const WebFrameProxy * ancestor) const221 bool WebFrameProxy::isDescendantOf(const WebFrameProxy* ancestor) const
222 {
223 if (!ancestor)
224 return false;
225
226 if (m_page != ancestor->m_page)
227 return false;
228
229 for (const WebFrameProxy* frame = this; frame; frame = frame->m_parentFrame) {
230 if (frame == ancestor)
231 return true;
232 }
233
234 return false;
235 }
236
dumpFrameTreeToSTDOUT(unsigned indent)237 void WebFrameProxy::dumpFrameTreeToSTDOUT(unsigned indent)
238 {
239 if (!indent && m_parentFrame)
240 printf("NOTE: Printing subtree.\n");
241
242 for (unsigned i = 0; i < indent; ++i)
243 printf(" ");
244 printf("| FRAME %d %s\n", (int)m_frameID, m_url.utf8().data());
245
246 for (WebFrameProxy* child = m_firstChild; child; child = child->m_nextSibling)
247 child->dumpFrameTreeToSTDOUT(indent + 4);
248 }
249
didRemoveFromHierarchy()250 void WebFrameProxy::didRemoveFromHierarchy()
251 {
252 if (m_parentFrame)
253 m_parentFrame->removeChild(this);
254 }
255
childFrames()256 PassRefPtr<ImmutableArray> WebFrameProxy::childFrames()
257 {
258 if (!m_firstChild)
259 return ImmutableArray::create();
260
261 Vector<RefPtr<APIObject> > vector;
262 for (WebFrameProxy* child = m_firstChild; child; child = child->m_nextSibling)
263 vector.append(child);
264
265 return ImmutableArray::adopt(vector);
266 }
267
receivedPolicyDecision(WebCore::PolicyAction action,uint64_t listenerID)268 void WebFrameProxy::receivedPolicyDecision(WebCore::PolicyAction action, uint64_t listenerID)
269 {
270 if (!m_page)
271 return;
272
273 ASSERT(m_activeListener);
274 ASSERT(m_activeListener->listenerID() == listenerID);
275 m_page->receivedPolicyDecision(action, this, listenerID);
276 }
277
setUpPolicyListenerProxy(uint64_t listenerID)278 WebFramePolicyListenerProxy* WebFrameProxy::setUpPolicyListenerProxy(uint64_t listenerID)
279 {
280 if (m_activeListener)
281 m_activeListener->invalidate();
282 m_activeListener = WebFramePolicyListenerProxy::create(this, listenerID);
283 return static_cast<WebFramePolicyListenerProxy*>(m_activeListener.get());
284 }
285
setUpFormSubmissionListenerProxy(uint64_t listenerID)286 WebFormSubmissionListenerProxy* WebFrameProxy::setUpFormSubmissionListenerProxy(uint64_t listenerID)
287 {
288 if (m_activeListener)
289 m_activeListener->invalidate();
290 m_activeListener = WebFormSubmissionListenerProxy::create(this, listenerID);
291 return static_cast<WebFormSubmissionListenerProxy*>(m_activeListener.get());
292 }
293
getWebArchive(PassRefPtr<DataCallback> callback)294 void WebFrameProxy::getWebArchive(PassRefPtr<DataCallback> callback)
295 {
296 if (!m_page) {
297 callback->invalidate();
298 return;
299 }
300
301 m_page->getWebArchiveOfFrame(this, callback);
302 }
303
getMainResourceData(PassRefPtr<DataCallback> callback)304 void WebFrameProxy::getMainResourceData(PassRefPtr<DataCallback> callback)
305 {
306 if (!m_page) {
307 callback->invalidate();
308 return;
309 }
310
311 m_page->getMainResourceDataOfFrame(this, callback);
312 }
313
getResourceData(WebURL * resourceURL,PassRefPtr<DataCallback> callback)314 void WebFrameProxy::getResourceData(WebURL* resourceURL, PassRefPtr<DataCallback> callback)
315 {
316 if (!m_page) {
317 callback->invalidate();
318 return;
319 }
320
321 m_page->getResourceDataFromFrame(this, resourceURL, callback);
322 }
323
324 } // namespace WebKit
325