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