PDFPlugin should make use of PDFKit's fluid zooming
[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/AnimationController.h>
46 #include <WebCore/ArchiveResource.h>
47 #include <WebCore/CSSComputedStyleDeclaration.h>
48 #include <WebCore/Chrome.h>
49 #include <WebCore/DocumentLoader.h>
50 #include <WebCore/Frame.h>
51 #include <WebCore/FrameView.h>
52 #include <WebCore/HTMLFrameOwnerElement.h>
53 #include <WebCore/HTMLNames.h>
54 #include <WebCore/JSCSSStyleDeclaration.h>
55 #include <WebCore/JSElement.h>
56 #include <WebCore/JSRange.h>
57 #include <WebCore/Page.h>
58 #include <WebCore/PluginDocument.h>
59 #include <WebCore/RenderTreeAsText.h>
60 #include <WebCore/ResourceBuffer.h>
61 #include <WebCore/SecurityOrigin.h>
62 #include <WebCore/TextIterator.h>
63 #include <WebCore/TextResourceDecoder.h>
64 #include <wtf/text/StringBuilder.h>
65
66 #if ENABLE(WEB_INTENTS)
67 #include "IntentData.h"
68 #include <WebCore/DOMWindowIntents.h>
69 #include <WebCore/DeliveredIntent.h>
70 #include <WebCore/Intent.h>
71 #include <WebCore/PlatformMessagePortChannel.h>
72 #endif
73
74 #if PLATFORM(MAC) || PLATFORM(WIN)
75 #include <WebCore/LegacyWebArchive.h>
76 #endif
77
78 #ifndef NDEBUG
79 #include <wtf/RefCountedLeakCounter.h>
80 #endif
81
82 using namespace JSC;
83 using namespace WebCore;
84
85 namespace WebKit {
86
87 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webFrameCounter, ("WebFrame"));
88
89 static uint64_t generateFrameID()
90 {
91     static uint64_t uniqueFrameID = 1;
92     return uniqueFrameID++;
93 }
94
95 static uint64_t generateListenerID()
96 {
97     static uint64_t uniqueListenerID = 1;
98     return uniqueListenerID++;
99 }
100
101 PassRefPtr<WebFrame> WebFrame::createMainFrame(WebPage* page)
102 {
103     RefPtr<WebFrame> frame = create();
104
105     page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID()));
106
107     frame->init(page, String(), 0);
108
109     return frame.release();
110 }
111
112 PassRefPtr<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
113 {
114     RefPtr<WebFrame> frame = create();
115
116     WebFrame* parentFrame = static_cast<WebFrameLoaderClient*>(ownerElement->document()->frame()->loader()->client())->webFrame();
117     page->send(Messages::WebPageProxy::DidCreateSubframe(frame->frameID(), parentFrame->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 (WebCore::Page* page = m_coreFrame->page())
180         return static_cast<WebChromeClient*>(page->chrome()->client())->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     DownloadManager::shared().startDownload(m_policyDownloadID, page(), request);
239
240     m_policyDownloadID = 0;
241 }
242
243 void WebFrame::convertHandleToDownload(ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& response)
244 {
245     ASSERT(m_policyDownloadID);
246
247     DownloadManager::shared().convertHandleToDownload(m_policyDownloadID, page(), handle, request, response);
248     m_policyDownloadID = 0;
249 }
250
251 #if ENABLE(WEB_INTENTS)
252 void WebFrame::deliverIntent(const IntentData& intentData)
253 {
254     OwnPtr<DeliveredIntentClient> dummyClient;
255     Vector<uint8_t> dataCopy = intentData.data;
256
257     OwnPtr<WebCore::MessagePortChannelArray> channels;
258     if (!intentData.messagePorts.isEmpty()) {
259         channels = adoptPtr(new WebCore::MessagePortChannelArray(intentData.messagePorts.size()));
260         for (size_t i = 0; i < intentData.messagePorts.size(); ++i)
261             (*channels)[i] = MessagePortChannel::create(WebProcess::shared().messagePortChannel(intentData.messagePorts.at(i)));
262     }
263     OwnPtr<WebCore::MessagePortArray> messagePorts = WebCore::MessagePort::entanglePorts(*m_coreFrame->document()->domWindow()->scriptExecutionContext(), channels.release());
264
265     RefPtr<DeliveredIntent> deliveredIntent = DeliveredIntent::create(m_coreFrame, dummyClient.release(), intentData.action, intentData.type,
266                                                                       SerializedScriptValue::adopt(dataCopy), messagePorts.release(),
267                                                                       intentData.extras);
268     WebCore::DOMWindowIntents::from(m_coreFrame->document()->domWindow())->deliver(deliveredIntent.release());
269 }
270
271 void WebFrame::deliverIntent(WebCore::Intent* intent)
272 {
273     OwnPtr<DeliveredIntentClient> dummyClient;
274
275     OwnPtr<WebCore::MessagePortChannelArray> channels;
276     WebCore::MessagePortChannelArray* origChannels = intent->messagePorts();
277     if (origChannels && origChannels->size()) {
278         channels = adoptPtr(new WebCore::MessagePortChannelArray(origChannels->size()));
279         for (size_t i = 0; i < origChannels->size(); ++i)
280             (*channels)[i] = origChannels->at(i).release();
281     }
282     OwnPtr<WebCore::MessagePortArray> messagePorts = WebCore::MessagePort::entanglePorts(*m_coreFrame->document()->domWindow()->scriptExecutionContext(), channels.release());
283
284     RefPtr<DeliveredIntent> deliveredIntent = DeliveredIntent::create(m_coreFrame, dummyClient.release(), intent->action(), intent->type(),
285                                                                       intent->data(), messagePorts.release(), intent->extras());
286     WebCore::DOMWindowIntents::from(m_coreFrame->document()->domWindow())->deliver(deliveredIntent.release());
287 }
288 #endif
289
290 String WebFrame::source() const 
291 {
292     if (!m_coreFrame)
293         return String();
294     Document* document = m_coreFrame->document();
295     if (!document)
296         return String();
297     TextResourceDecoder* decoder = document->decoder();
298     if (!decoder)
299         return String();
300     DocumentLoader* documentLoader = m_coreFrame->loader()->activeDocumentLoader();
301     if (!documentLoader)
302         return String();
303     RefPtr<ResourceBuffer> mainResourceData = documentLoader->mainResourceData();
304     if (!mainResourceData)
305         return String();
306     return decoder->encoding().decode(mainResourceData->data(), mainResourceData->size());
307 }
308
309 String WebFrame::contentsAsString() const 
310 {
311     if (!m_coreFrame)
312         return String();
313
314     if (isFrameSet()) {
315         StringBuilder builder;
316         for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
317             if (!builder.isEmpty())
318                 builder.append(' ');
319             builder.append(static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame()->contentsAsString());
320         }
321         // FIXME: It may make sense to use toStringPreserveCapacity() here.
322         return builder.toString();
323     }
324
325     Document* document = m_coreFrame->document();
326     if (!document)
327         return String();
328
329     RefPtr<Element> documentElement = document->documentElement();
330     if (!documentElement)
331         return String();
332
333     RefPtr<Range> range = document->createRange();
334
335     ExceptionCode ec = 0;
336     range->selectNode(documentElement.get(), ec);
337     if (ec)
338         return String();
339
340     return plainText(range.get());
341 }
342
343 String WebFrame::selectionAsString() const 
344 {
345     if (!m_coreFrame)
346         return String();
347
348     return m_coreFrame->displayStringModifiedByEncoding(m_coreFrame->editor()->selectedText());
349 }
350
351 IntSize WebFrame::size() const
352 {
353     if (!m_coreFrame)
354         return IntSize();
355
356     FrameView* frameView = m_coreFrame->view();
357     if (!frameView)
358         return IntSize();
359
360     return frameView->contentsSize();
361 }
362
363 bool WebFrame::isFrameSet() const
364 {
365     if (!m_coreFrame)
366         return false;
367
368     Document* document = m_coreFrame->document();
369     if (!document)
370         return false;
371     return document->isFrameSet();
372 }
373
374 bool WebFrame::isMainFrame() const
375 {
376     if (WebPage* p = page())
377         return p->mainWebFrame() == this;
378
379     return false;
380 }
381
382 String WebFrame::name() const
383 {
384     if (!m_coreFrame)
385         return String();
386
387     return m_coreFrame->tree()->uniqueName();
388 }
389
390 String WebFrame::url() const
391 {
392     if (!m_coreFrame)
393         return String();
394
395     DocumentLoader* documentLoader = m_coreFrame->loader()->documentLoader();
396     if (!documentLoader)
397         return String();
398
399     return documentLoader->url().string();
400 }
401
402 String WebFrame::innerText() const
403 {
404     if (!m_coreFrame)
405         return String();
406
407     if (!m_coreFrame->document()->documentElement())
408         return String();
409
410     return m_coreFrame->document()->documentElement()->innerText();
411 }
412
413 WebFrame* WebFrame::parentFrame() const
414 {
415     if (!m_coreFrame || !m_coreFrame->ownerElement() || !m_coreFrame->ownerElement()->document())
416         return 0;
417
418     return static_cast<WebFrameLoaderClient*>(m_coreFrame->ownerElement()->document()->frame()->loader()->client())->webFrame();
419 }
420
421 PassRefPtr<ImmutableArray> WebFrame::childFrames()
422 {
423     if (!m_coreFrame)
424         return ImmutableArray::create();
425
426     size_t size = m_coreFrame->tree()->childCount();
427     if (!size)
428         return ImmutableArray::create();
429
430     Vector<RefPtr<APIObject> > vector;
431     vector.reserveInitialCapacity(size);
432
433     for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
434         WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame();
435         vector.uncheckedAppend(webFrame);
436     }
437
438     return ImmutableArray::adopt(vector);
439 }
440
441 unsigned WebFrame::numberOfActiveAnimations() const
442 {
443     if (!m_coreFrame)
444         return 0;
445
446     AnimationController* controller = m_coreFrame->animation();
447     if (!controller)
448         return 0;
449
450     return controller->numberOfActiveAnimations(m_coreFrame->document());
451 }
452
453 bool WebFrame::pauseAnimationOnElementWithId(const String& animationName, const String& elementID, double time)
454 {
455     if (!m_coreFrame)
456         return false;
457
458     AnimationController* controller = m_coreFrame->animation();
459     if (!controller)
460         return false;
461
462     if (!m_coreFrame->document())
463         return false;
464
465     Node* coreNode = m_coreFrame->document()->getElementById(elementID);
466     if (!coreNode || !coreNode->renderer())
467         return false;
468
469     return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time);
470 }
471
472 bool WebFrame::pauseTransitionOnElementWithId(const String& propertyName, const String& elementID, double time)
473 {
474     if (!m_coreFrame)
475         return false;
476
477     AnimationController* controller = m_coreFrame->animation();
478     if (!controller)
479         return false;
480
481     if (!m_coreFrame->document())
482         return false;
483
484     Node* coreNode = m_coreFrame->document()->getElementById(elementID);
485     if (!coreNode || !coreNode->renderer())
486         return false;
487
488     return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time);
489 }
490
491 void WebFrame::suspendAnimations()
492 {
493     if (!m_coreFrame)
494         return;
495
496     AnimationController* controller = m_coreFrame->animation();
497     if (!controller)
498         return;
499
500     controller->suspendAnimations();
501 }
502
503 void WebFrame::resumeAnimations()
504 {
505     if (!m_coreFrame)
506         return;
507
508     AnimationController* controller = m_coreFrame->animation();
509     if (!controller)
510         return;
511
512     controller->resumeAnimations();
513 }
514
515 String WebFrame::layerTreeAsText() const
516 {
517     if (!m_coreFrame)
518         return "";
519
520     return m_coreFrame->layerTreeAsText(0);
521 }
522
523 unsigned WebFrame::pendingUnloadCount() const
524 {
525     if (!m_coreFrame)
526         return 0;
527
528     return m_coreFrame->document()->domWindow()->pendingUnloadEventListeners();
529 }
530
531 bool WebFrame::allowsFollowingLink(const WebCore::KURL& url) const
532 {
533     if (!m_coreFrame)
534         return true;
535         
536     return m_coreFrame->document()->securityOrigin()->canDisplay(url);
537 }
538
539 JSGlobalContextRef WebFrame::jsContext()
540 {
541     return toGlobalRef(m_coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
542 }
543
544 JSGlobalContextRef WebFrame::jsContextForWorld(InjectedBundleScriptWorld* world)
545 {
546     return toGlobalRef(m_coreFrame->script()->globalObject(world->coreWorld())->globalExec());
547 }
548
549 bool WebFrame::handlesPageScaleGesture() const
550 {
551     if (!m_coreFrame->document()->isPluginDocument())
552         return 0;
553
554     PluginDocument* pluginDocument = static_cast<PluginDocument*>(m_coreFrame->document());
555     PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
556
557     return pluginView->handlesPageScaleFactor();
558 }
559
560 IntRect WebFrame::contentBounds() const
561 {    
562     if (!m_coreFrame)
563         return IntRect();
564     
565     FrameView* view = m_coreFrame->view();
566     if (!view)
567         return IntRect();
568     
569     return IntRect(0, 0, view->contentsWidth(), view->contentsHeight());
570 }
571
572 IntRect WebFrame::visibleContentBounds() const
573 {
574     if (!m_coreFrame)
575         return IntRect();
576     
577     FrameView* view = m_coreFrame->view();
578     if (!view)
579         return IntRect();
580     
581     IntRect contentRect = view->visibleContentRect(true);
582     return IntRect(0, 0, contentRect.width(), contentRect.height());
583 }
584
585 IntRect WebFrame::visibleContentBoundsExcludingScrollbars() const
586 {
587     if (!m_coreFrame)
588         return IntRect();
589     
590     FrameView* view = m_coreFrame->view();
591     if (!view)
592         return IntRect();
593     
594     IntRect contentRect = view->visibleContentRect(false);
595     return IntRect(0, 0, contentRect.width(), contentRect.height());
596 }
597
598 IntSize WebFrame::scrollOffset() const
599 {
600     if (!m_coreFrame)
601         return IntSize();
602     
603     FrameView* view = m_coreFrame->view();
604     if (!view)
605         return IntSize();
606
607     return view->scrollOffset();
608 }
609
610 bool WebFrame::hasHorizontalScrollbar() const
611 {
612     if (!m_coreFrame)
613         return false;
614
615     FrameView* view = m_coreFrame->view();
616     if (!view)
617         return false;
618
619     return view->horizontalScrollbar();
620 }
621
622 bool WebFrame::hasVerticalScrollbar() const
623 {
624     if (!m_coreFrame)
625         return false;
626
627     FrameView* view = m_coreFrame->view();
628     if (!view)
629         return false;
630
631     return view->verticalScrollbar();
632 }
633
634 PassRefPtr<InjectedBundleHitTestResult> WebFrame::hitTest(const IntPoint point) const
635 {
636     if (!m_coreFrame)
637         return 0;
638
639     return InjectedBundleHitTestResult::create(m_coreFrame->eventHandler()->hitTestResultAtPoint(point, false, true));
640 }
641
642 bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha)
643 {
644     if (!m_coreFrame)
645         return false;
646
647     FrameView* view = m_coreFrame->view();
648     if (!view)
649         return false;
650
651     Color bgColor = view->documentBackgroundColor();
652     if (!bgColor.isValid())
653         return false;
654
655     bgColor.getRGBA(*red, *green, *blue, *alpha);
656     return true;
657 }
658
659 bool WebFrame::containsAnyFormElements() const
660 {
661     if (!m_coreFrame)
662         return false;
663     
664     Document* document = m_coreFrame->document();
665     if (!document)
666         return false;
667
668     for (Node* node = document->documentElement(); node; node = node->traverseNextNode()) {
669         if (!node->isElementNode())
670             continue;
671         if (static_cast<Element*>(node)->hasTagName(HTMLNames::formTag))
672             return true;
673     }
674     return false;
675 }
676
677 void WebFrame::stopLoading()
678 {
679     if (!m_coreFrame)
680         return;
681
682     m_coreFrame->loader()->stopForUserCancel();
683 }
684
685 WebFrame* WebFrame::frameForContext(JSContextRef context)
686 {
687     JSObjectRef globalObjectRef = JSContextGetGlobalObject(context);
688     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
689     if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0)
690         return 0;
691
692     Frame* coreFrame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->impl()->frame();
693     return static_cast<WebFrameLoaderClient*>(coreFrame->loader()->client())->webFrame();
694 }
695
696 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world)
697 {
698     if (!m_coreFrame)
699         return 0;
700
701     JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(world->coreWorld());
702     ExecState* exec = globalObject->globalExec();
703
704     JSLockHolder lock(exec);
705     return toRef(exec, toJS(exec, globalObject, nodeHandle->coreNode()));
706 }
707
708 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleRangeHandle* rangeHandle, InjectedBundleScriptWorld* world)
709 {
710     if (!m_coreFrame)
711         return 0;
712
713     JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(world->coreWorld());
714     ExecState* exec = globalObject->globalExec();
715
716     JSLockHolder lock(exec);
717     return toRef(exec, toJS(exec, globalObject, rangeHandle->coreRange()));
718 }
719
720 JSValueRef WebFrame::computedStyleIncludingVisitedInfo(JSObjectRef element)
721 {
722     if (!m_coreFrame)
723         return 0;
724
725     JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(mainThreadNormalWorld());
726     ExecState* exec = globalObject->globalExec();
727
728     if (!toJS(element)->inherits(&JSElement::s_info))
729         return JSValueMakeUndefined(toRef(exec));
730
731     RefPtr<CSSComputedStyleDeclaration> style = CSSComputedStyleDeclaration::create(static_cast<JSElement*>(toJS(element))->impl(), true);
732
733     JSLockHolder lock(exec);
734     return toRef(exec, toJS(exec, globalObject, style.get()));
735 }
736
737 String WebFrame::counterValue(JSObjectRef element)
738 {
739     if (!toJS(element)->inherits(&JSElement::s_info))
740         return String();
741
742     return counterValueForElement(static_cast<JSElement*>(toJS(element))->impl());
743 }
744
745 String WebFrame::markerText(JSObjectRef element)
746 {
747     if (!toJS(element)->inherits(&JSElement::s_info))
748         return String();
749
750     return markerTextForListItem(static_cast<JSElement*>(toJS(element))->impl());
751 }
752
753 String WebFrame::provisionalURL() const
754 {
755     if (!m_coreFrame)
756         return String();
757
758     return m_coreFrame->loader()->provisionalDocumentLoader()->url().string();
759 }
760
761 String WebFrame::suggestedFilenameForResourceWithURL(const KURL& url) const
762 {
763     if (!m_coreFrame)
764         return String();
765
766     DocumentLoader* loader = m_coreFrame->loader()->documentLoader();
767     if (!loader)
768         return String();
769
770     // First, try the main resource.
771     if (loader->url() == url)
772         return loader->response().suggestedFilename();
773
774     // Next, try subresources.
775     RefPtr<ArchiveResource> resource = loader->subresource(url);
776     if (resource)
777         return resource->response().suggestedFilename();
778
779     return page()->cachedSuggestedFilenameForURL(url);
780 }
781
782 String WebFrame::mimeTypeForResourceWithURL(const KURL& url) const
783 {
784     if (!m_coreFrame)
785         return String();
786
787     DocumentLoader* loader = m_coreFrame->loader()->documentLoader();
788     if (!loader)
789         return String();
790
791     // First, try the main resource.
792     if (loader->url() == url)
793         return loader->response().mimeType();
794
795     // Next, try subresources.
796     RefPtr<ArchiveResource> resource = loader->subresource(url);
797     if (resource)
798         return resource->mimeType();
799
800     return page()->cachedResponseMIMETypeForURL(url);
801 }
802
803 void WebFrame::setTextDirection(const String& direction)
804 {
805     if (!m_coreFrame || !m_coreFrame->editor())
806         return;
807
808     if (direction == "auto")
809         m_coreFrame->editor()->setBaseWritingDirection(NaturalWritingDirection);
810     else if (direction == "ltr")
811         m_coreFrame->editor()->setBaseWritingDirection(LeftToRightWritingDirection);
812     else if (direction == "rtl")
813         m_coreFrame->editor()->setBaseWritingDirection(RightToLeftWritingDirection);
814 }
815
816 #if PLATFORM(MAC) || PLATFORM(WIN)
817
818 class WebFrameFilter : public FrameFilter {
819 public:
820     WebFrameFilter(WebFrame*, WebFrame::FrameFilterFunction, void* context);
821         
822 private:
823     virtual bool shouldIncludeSubframe(Frame*) const OVERRIDE;
824
825     WebFrame* m_topLevelWebFrame;
826     WebFrame::FrameFilterFunction m_callback;
827     void* m_context;
828 };
829
830 WebFrameFilter::WebFrameFilter(WebFrame* topLevelWebFrame, WebFrame::FrameFilterFunction callback, void* context)
831     : m_topLevelWebFrame(topLevelWebFrame)
832     , m_callback(callback)
833     , m_context(context)
834 {
835 }
836
837 bool WebFrameFilter::shouldIncludeSubframe(Frame* frame) const
838 {
839     if (!m_callback)
840         return true;
841         
842     WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(frame->loader()->client())->webFrame();
843     return m_callback(toAPI(m_topLevelWebFrame), toAPI(webFrame), m_context);
844 }
845
846 RetainPtr<CFDataRef> WebFrame::webArchiveData(FrameFilterFunction callback, void* context)
847 {
848     WebFrameFilter filter(this, callback, context);
849
850     if (RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(coreFrame()->document(), &filter))
851         return archive->rawDataRepresentation();
852     
853     return 0;
854 }
855 #endif
856     
857 } // namespace WebKit