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