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