Frame::editor() should return a reference
[WebKit-https.git] / Source / 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 "config.h"
27 #include "WebFrame.h"
28
29 #include "DownloadManager.h"
30 #include "InjectedBundleHitTestResult.h"
31 #include "InjectedBundleNodeHandle.h"
32 #include "InjectedBundleRangeHandle.h"
33 #include "InjectedBundleScriptWorld.h"
34 #include "PluginView.h"
35 #include "WKAPICast.h"
36 #include "WKBundleAPICast.h"
37 #include "WebChromeClient.h"
38 #include "WebPage.h"
39 #include "WebPageProxyMessages.h"
40 #include "WebProcess.h"
41 #include <JavaScriptCore/APICast.h>
42 #include <JavaScriptCore/JSContextRef.h>
43 #include <JavaScriptCore/JSLock.h>
44 #include <JavaScriptCore/JSValueRef.h>
45 #include <WebCore/ArchiveResource.h>
46 #include <WebCore/Chrome.h>
47 #include <WebCore/DocumentLoader.h>
48 #include <WebCore/EventHandler.h>
49 #include <WebCore/Frame.h>
50 #include <WebCore/FrameView.h>
51 #include <WebCore/HTMLFrameOwnerElement.h>
52 #include <WebCore/HTMLNames.h>
53 #include <WebCore/JSCSSStyleDeclaration.h>
54 #include <WebCore/JSElement.h>
55 #include <WebCore/JSRange.h>
56 #include <WebCore/NetworkingContext.h>
57 #include <WebCore/NodeTraversal.h>
58 #include <WebCore/Page.h>
59 #include <WebCore/PluginDocument.h>
60 #include <WebCore/RenderTreeAsText.h>
61 #include <WebCore/ResourceBuffer.h>
62 #include <WebCore/ResourceLoader.h>
63 #include <WebCore/ScriptController.h>
64 #include <WebCore/SecurityOrigin.h>
65 #include <WebCore/TextIterator.h>
66 #include <WebCore/TextResourceDecoder.h>
67 #include <wtf/text/StringBuilder.h>
68
69 #if PLATFORM(MAC)
70 #include <WebCore/LegacyWebArchive.h>
71 #endif
72
73 #if ENABLE(NETWORK_PROCESS)
74 #include "NetworkConnectionToWebProcessMessages.h"
75 #include "NetworkProcessConnection.h"
76 #include "WebCoreArgumentCoders.h"
77 #endif
78
79 #ifndef NDEBUG
80 #include <wtf/RefCountedLeakCounter.h>
81 #endif
82
83 using namespace JSC;
84 using namespace WebCore;
85
86 namespace WebKit {
87
88 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webFrameCounter, ("WebFrame"));
89
90 static uint64_t generateFrameID()
91 {
92     static uint64_t uniqueFrameID = 1;
93     return uniqueFrameID++;
94 }
95
96 static uint64_t generateListenerID()
97 {
98     static uint64_t uniqueListenerID = 1;
99     return uniqueListenerID++;
100 }
101
102 PassRefPtr<WebFrame> WebFrame::createMainFrame(WebPage* page)
103 {
104     RefPtr<WebFrame> frame = create();
105
106     page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID()));
107
108     frame->init(page, String(), 0);
109
110     return frame.release();
111 }
112
113 PassRefPtr<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
114 {
115     RefPtr<WebFrame> frame = create();
116
117     page->send(Messages::WebPageProxy::DidCreateSubframe(frame->frameID()));
118
119     frame->init(page, frameName, ownerElement);
120
121     return frame.release();
122 }
123
124 PassRefPtr<WebFrame> WebFrame::create()
125 {
126     RefPtr<WebFrame> frame = adoptRef(new WebFrame);
127
128     // Add explict ref() that will be balanced in WebFrameLoaderClient::frameLoaderDestroyed().
129     frame->ref();
130
131     return frame.release();
132 }
133
134 WebFrame::WebFrame()
135     : m_coreFrame(0)
136     , m_policyListenerID(0)
137     , m_policyFunction(0)
138     , m_policyDownloadID(0)
139     , m_frameLoaderClient(this)
140     , m_loadListener(0)
141     , m_frameID(generateFrameID())
142 {
143     WebProcess::shared().addWebFrame(m_frameID, this);
144
145 #ifndef NDEBUG
146     webFrameCounter.increment();
147 #endif
148 }
149
150 WebFrame::~WebFrame()
151 {
152     ASSERT(!m_coreFrame);
153
154 #ifndef NDEBUG
155     webFrameCounter.decrement();
156 #endif
157 }
158
159 void WebFrame::init(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
160 {
161     RefPtr<Frame> frame = Frame::create(page->corePage(), ownerElement, &m_frameLoaderClient);
162     m_coreFrame = frame.get();
163
164     frame->tree()->setName(frameName);
165
166     if (ownerElement) {
167         ASSERT(ownerElement->document()->frame());
168         ownerElement->document()->frame()->tree()->appendChild(frame);
169     }
170
171     frame->init();
172 }
173
174 WebPage* WebFrame::page() const
175
176     if (!m_coreFrame)
177         return 0;
178     
179     if (Page* page = m_coreFrame->page())
180         return WebPage::fromCorePage(page);
181
182     return 0;
183 }
184
185 void WebFrame::invalidate()
186 {
187     WebProcess::shared().removeWebFrame(m_frameID);
188     m_coreFrame = 0;
189 }
190
191 uint64_t WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction policyFunction)
192 {
193     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
194
195     invalidatePolicyListener();
196
197     m_policyListenerID = generateListenerID();
198     m_policyFunction = policyFunction;
199     return m_policyListenerID;
200 }
201
202 void WebFrame::invalidatePolicyListener()
203 {
204     if (!m_policyListenerID)
205         return;
206
207     m_policyDownloadID = 0;
208     m_policyListenerID = 0;
209     m_policyFunction = 0;
210 }
211
212 void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action, uint64_t downloadID)
213 {
214     if (!m_coreFrame)
215         return;
216
217     if (!m_policyListenerID)
218         return;
219
220     if (listenerID != m_policyListenerID)
221         return;
222
223     ASSERT(m_policyFunction);
224
225     FramePolicyFunction function = m_policyFunction;
226
227     invalidatePolicyListener();
228
229     m_policyDownloadID = downloadID;
230
231     (m_coreFrame->loader()->policyChecker()->*function)(action);
232 }
233
234 void WebFrame::startDownload(const WebCore::ResourceRequest& request)
235 {
236     ASSERT(m_policyDownloadID);
237
238     uint64_t policyDownloadID = m_policyDownloadID;
239     m_policyDownloadID = 0;
240
241 #if ENABLE(NETWORK_PROCESS)
242     if (WebProcess::shared().usesNetworkProcess()) {
243         bool privateBrowsingEnabled = m_coreFrame->loader()->networkingContext()->storageSession().isPrivateBrowsingSession();
244         WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::StartDownload(privateBrowsingEnabled, policyDownloadID, request), 0);
245         return;
246     }
247 #endif
248
249     WebProcess::shared().downloadManager().startDownload(policyDownloadID, request);
250 }
251
252 void WebFrame::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, const ResourceRequest& request, const ResourceResponse& response)
253 {
254     ASSERT(m_policyDownloadID);
255
256     uint64_t policyDownloadID = m_policyDownloadID;
257     m_policyDownloadID = 0;
258
259 #if ENABLE(NETWORK_PROCESS)
260     if (WebProcess::shared().usesNetworkProcess()) {
261         WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::ConvertMainResourceLoadToDownload(documentLoader->mainResourceLoader()->identifier(), policyDownloadID, request, response), 0);
262         return;
263     }
264 #endif
265
266     WebProcess::shared().downloadManager().convertHandleToDownload(policyDownloadID, documentLoader->mainResourceLoader()->handle(), request, response);
267 }
268
269 String WebFrame::source() const 
270 {
271     if (!m_coreFrame)
272         return String();
273     Document* document = m_coreFrame->document();
274     if (!document)
275         return String();
276     TextResourceDecoder* decoder = document->decoder();
277     if (!decoder)
278         return String();
279     DocumentLoader* documentLoader = m_coreFrame->loader()->activeDocumentLoader();
280     if (!documentLoader)
281         return String();
282     RefPtr<ResourceBuffer> mainResourceData = documentLoader->mainResourceData();
283     if (!mainResourceData)
284         return String();
285     return decoder->encoding().decode(mainResourceData->data(), mainResourceData->size());
286 }
287
288 String WebFrame::contentsAsString() const 
289 {
290     if (!m_coreFrame)
291         return String();
292
293     if (isFrameSet()) {
294         StringBuilder builder;
295         for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
296             if (!builder.isEmpty())
297                 builder.append(' ');
298             builder.append(static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame()->contentsAsString());
299         }
300         // FIXME: It may make sense to use toStringPreserveCapacity() here.
301         return builder.toString();
302     }
303
304     Document* document = m_coreFrame->document();
305     if (!document)
306         return String();
307
308     RefPtr<Element> documentElement = document->documentElement();
309     if (!documentElement)
310         return String();
311
312     RefPtr<Range> range = document->createRange();
313
314     ExceptionCode ec = 0;
315     range->selectNode(documentElement.get(), ec);
316     if (ec)
317         return String();
318
319     return plainText(range.get());
320 }
321
322 String WebFrame::selectionAsString() const 
323 {
324     if (!m_coreFrame)
325         return String();
326
327     return m_coreFrame->displayStringModifiedByEncoding(m_coreFrame->editor().selectedText());
328 }
329
330 IntSize WebFrame::size() const
331 {
332     if (!m_coreFrame)
333         return IntSize();
334
335     FrameView* frameView = m_coreFrame->view();
336     if (!frameView)
337         return IntSize();
338
339     return frameView->contentsSize();
340 }
341
342 bool WebFrame::isFrameSet() const
343 {
344     if (!m_coreFrame)
345         return false;
346
347     Document* document = m_coreFrame->document();
348     if (!document)
349         return false;
350     return document->isFrameSet();
351 }
352
353 bool WebFrame::isMainFrame() const
354 {
355     if (WebPage* p = page())
356         return p->mainWebFrame() == this;
357
358     return false;
359 }
360
361 String WebFrame::name() const
362 {
363     if (!m_coreFrame)
364         return String();
365
366     return m_coreFrame->tree()->uniqueName();
367 }
368
369 String WebFrame::url() const
370 {
371     if (!m_coreFrame)
372         return String();
373
374     DocumentLoader* documentLoader = m_coreFrame->loader()->documentLoader();
375     if (!documentLoader)
376         return String();
377
378     return documentLoader->url().string();
379 }
380
381 String WebFrame::innerText() const
382 {
383     if (!m_coreFrame)
384         return String();
385
386     if (!m_coreFrame->document()->documentElement())
387         return String();
388
389     return m_coreFrame->document()->documentElement()->innerText();
390 }
391
392 WebFrame* WebFrame::parentFrame() const
393 {
394     if (!m_coreFrame || !m_coreFrame->ownerElement() || !m_coreFrame->ownerElement()->document())
395         return 0;
396
397     return static_cast<WebFrameLoaderClient*>(m_coreFrame->ownerElement()->document()->frame()->loader()->client())->webFrame();
398 }
399
400 PassRefPtr<ImmutableArray> WebFrame::childFrames()
401 {
402     if (!m_coreFrame)
403         return ImmutableArray::create();
404
405     size_t size = m_coreFrame->tree()->childCount();
406     if (!size)
407         return ImmutableArray::create();
408
409     Vector<RefPtr<APIObject>> vector;
410     vector.reserveInitialCapacity(size);
411
412     for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
413         WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame();
414         vector.uncheckedAppend(webFrame);
415     }
416
417     return ImmutableArray::adopt(vector);
418 }
419
420 String WebFrame::layerTreeAsText() const
421 {
422     if (!m_coreFrame)
423         return "";
424
425     return m_coreFrame->layerTreeAsText(0);
426 }
427
428 unsigned WebFrame::pendingUnloadCount() const
429 {
430     if (!m_coreFrame)
431         return 0;
432
433     return m_coreFrame->document()->domWindow()->pendingUnloadEventListeners();
434 }
435
436 bool WebFrame::allowsFollowingLink(const WebCore::KURL& url) const
437 {
438     if (!m_coreFrame)
439         return true;
440         
441     return m_coreFrame->document()->securityOrigin()->canDisplay(url);
442 }
443
444 JSGlobalContextRef WebFrame::jsContext()
445 {
446     return toGlobalRef(m_coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
447 }
448
449 JSGlobalContextRef WebFrame::jsContextForWorld(InjectedBundleScriptWorld* world)
450 {
451     return toGlobalRef(m_coreFrame->script()->globalObject(world->coreWorld())->globalExec());
452 }
453
454 bool WebFrame::handlesPageScaleGesture() const
455 {
456     if (!m_coreFrame->document()->isPluginDocument())
457         return 0;
458
459     PluginDocument* pluginDocument = static_cast<PluginDocument*>(m_coreFrame->document());
460     PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
461
462     return pluginView->handlesPageScaleFactor();
463 }
464
465 IntRect WebFrame::contentBounds() const
466 {    
467     if (!m_coreFrame)
468         return IntRect();
469     
470     FrameView* view = m_coreFrame->view();
471     if (!view)
472         return IntRect();
473     
474     return IntRect(0, 0, view->contentsWidth(), view->contentsHeight());
475 }
476
477 IntRect WebFrame::visibleContentBounds() const
478 {
479     if (!m_coreFrame)
480         return IntRect();
481     
482     FrameView* view = m_coreFrame->view();
483     if (!view)
484         return IntRect();
485     
486     IntRect contentRect = view->visibleContentRect(ScrollableArea::IncludeScrollbars);
487     return IntRect(0, 0, contentRect.width(), contentRect.height());
488 }
489
490 IntRect WebFrame::visibleContentBoundsExcludingScrollbars() const
491 {
492     if (!m_coreFrame)
493         return IntRect();
494     
495     FrameView* view = m_coreFrame->view();
496     if (!view)
497         return IntRect();
498     
499     IntRect contentRect = view->visibleContentRect();
500     return IntRect(0, 0, contentRect.width(), contentRect.height());
501 }
502
503 IntSize WebFrame::scrollOffset() const
504 {
505     if (!m_coreFrame)
506         return IntSize();
507     
508     FrameView* view = m_coreFrame->view();
509     if (!view)
510         return IntSize();
511
512     return view->scrollOffset();
513 }
514
515 bool WebFrame::hasHorizontalScrollbar() const
516 {
517     if (!m_coreFrame)
518         return false;
519
520     FrameView* view = m_coreFrame->view();
521     if (!view)
522         return false;
523
524     return view->horizontalScrollbar();
525 }
526
527 bool WebFrame::hasVerticalScrollbar() const
528 {
529     if (!m_coreFrame)
530         return false;
531
532     FrameView* view = m_coreFrame->view();
533     if (!view)
534         return false;
535
536     return view->verticalScrollbar();
537 }
538
539 PassRefPtr<InjectedBundleHitTestResult> WebFrame::hitTest(const IntPoint point) const
540 {
541     if (!m_coreFrame)
542         return 0;
543
544     return InjectedBundleHitTestResult::create(m_coreFrame->eventHandler()->hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent));
545 }
546
547 bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha)
548 {
549     if (!m_coreFrame)
550         return false;
551
552     FrameView* view = m_coreFrame->view();
553     if (!view)
554         return false;
555
556     Color bgColor = view->documentBackgroundColor();
557     if (!bgColor.isValid())
558         return false;
559
560     bgColor.getRGBA(*red, *green, *blue, *alpha);
561     return true;
562 }
563
564 bool WebFrame::containsAnyFormElements() const
565 {
566     if (!m_coreFrame)
567         return false;
568     
569     Document* document = m_coreFrame->document();
570     if (!document)
571         return false;
572
573     for (Node* node = document->documentElement(); node; node = NodeTraversal::next(node)) {
574         if (!node->isElementNode())
575             continue;
576         if (toElement(node)->hasTagName(HTMLNames::formTag))
577             return true;
578     }
579     return false;
580 }
581
582 bool WebFrame::containsAnyFormControls() const
583 {
584     if (!m_coreFrame)
585         return false;
586     
587     Document* document = m_coreFrame->document();
588     if (!document)
589         return false;
590
591     for (Node* node = document->documentElement(); node; node = NodeTraversal::next(node)) {
592         if (!node->isElementNode())
593             continue;
594         if (toElement(node)->hasTagName(HTMLNames::inputTag) || toElement(node)->hasTagName(HTMLNames::selectTag) || toElement(node)->hasTagName(HTMLNames::textareaTag))
595             return true;
596     }
597     return false;
598 }
599
600 void WebFrame::stopLoading()
601 {
602     if (!m_coreFrame)
603         return;
604
605     m_coreFrame->loader()->stopForUserCancel();
606 }
607
608 WebFrame* WebFrame::frameForContext(JSContextRef context)
609 {
610     JSObjectRef globalObjectRef = JSContextGetGlobalObject(context);
611     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
612     if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0)
613         return 0;
614
615     Frame* coreFrame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->impl()->frame();
616     return static_cast<WebFrameLoaderClient*>(coreFrame->loader()->client())->webFrame();
617 }
618
619 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world)
620 {
621     if (!m_coreFrame)
622         return 0;
623
624     JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(world->coreWorld());
625     ExecState* exec = globalObject->globalExec();
626
627     JSLockHolder lock(exec);
628     return toRef(exec, toJS(exec, globalObject, nodeHandle->coreNode()));
629 }
630
631 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleRangeHandle* rangeHandle, InjectedBundleScriptWorld* world)
632 {
633     if (!m_coreFrame)
634         return 0;
635
636     JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(world->coreWorld());
637     ExecState* exec = globalObject->globalExec();
638
639     JSLockHolder lock(exec);
640     return toRef(exec, toJS(exec, globalObject, rangeHandle->coreRange()));
641 }
642
643 String WebFrame::counterValue(JSObjectRef element)
644 {
645     if (!toJS(element)->inherits(&JSElement::s_info))
646         return String();
647
648     return counterValueForElement(static_cast<JSElement*>(toJS(element))->impl());
649 }
650
651 String WebFrame::provisionalURL() const
652 {
653     if (!m_coreFrame)
654         return String();
655
656     return m_coreFrame->loader()->provisionalDocumentLoader()->url().string();
657 }
658
659 String WebFrame::suggestedFilenameForResourceWithURL(const KURL& url) const
660 {
661     if (!m_coreFrame)
662         return String();
663
664     DocumentLoader* loader = m_coreFrame->loader()->documentLoader();
665     if (!loader)
666         return String();
667
668     // First, try the main resource.
669     if (loader->url() == url)
670         return loader->response().suggestedFilename();
671
672     // Next, try subresources.
673     RefPtr<ArchiveResource> resource = loader->subresource(url);
674     if (resource)
675         return resource->response().suggestedFilename();
676
677     return page()->cachedSuggestedFilenameForURL(url);
678 }
679
680 String WebFrame::mimeTypeForResourceWithURL(const KURL& url) const
681 {
682     if (!m_coreFrame)
683         return String();
684
685     DocumentLoader* loader = m_coreFrame->loader()->documentLoader();
686     if (!loader)
687         return String();
688
689     // First, try the main resource.
690     if (loader->url() == url)
691         return loader->response().mimeType();
692
693     // Next, try subresources.
694     RefPtr<ArchiveResource> resource = loader->subresource(url);
695     if (resource)
696         return resource->mimeType();
697
698     return page()->cachedResponseMIMETypeForURL(url);
699 }
700
701 void WebFrame::setTextDirection(const String& direction)
702 {
703     if (!m_coreFrame)
704         return;
705
706     if (direction == "auto")
707         m_coreFrame->editor().setBaseWritingDirection(NaturalWritingDirection);
708     else if (direction == "ltr")
709         m_coreFrame->editor().setBaseWritingDirection(LeftToRightWritingDirection);
710     else if (direction == "rtl")
711         m_coreFrame->editor().setBaseWritingDirection(RightToLeftWritingDirection);
712 }
713
714 #if PLATFORM(MAC)
715
716 class WebFrameFilter : public FrameFilter {
717 public:
718     WebFrameFilter(WebFrame*, WebFrame::FrameFilterFunction, void* context);
719         
720 private:
721     virtual bool shouldIncludeSubframe(Frame*) const OVERRIDE;
722
723     WebFrame* m_topLevelWebFrame;
724     WebFrame::FrameFilterFunction m_callback;
725     void* m_context;
726 };
727
728 WebFrameFilter::WebFrameFilter(WebFrame* topLevelWebFrame, WebFrame::FrameFilterFunction callback, void* context)
729     : m_topLevelWebFrame(topLevelWebFrame)
730     , m_callback(callback)
731     , m_context(context)
732 {
733 }
734
735 bool WebFrameFilter::shouldIncludeSubframe(Frame* frame) const
736 {
737     if (!m_callback)
738         return true;
739         
740     WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
741     return m_callback(toAPI(m_topLevelWebFrame), toAPI(webFrame), m_context);
742 }
743
744 RetainPtr<CFDataRef> WebFrame::webArchiveData(FrameFilterFunction callback, void* context)
745 {
746     WebFrameFilter filter(this, callback, context);
747
748     if (RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(coreFrame()->document(), &filter))
749         return archive->rawDataRepresentation();
750     
751     return 0;
752 }
753 #endif
754     
755 } // namespace WebKit