c37a7f9e8ebbc19b1e8681c85053aa10d4d0440a
[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 "APIArray.h"
30 #include "DownloadManager.h"
31 #include "InjectedBundleFileHandle.h"
32 #include "InjectedBundleHitTestResult.h"
33 #include "InjectedBundleNodeHandle.h"
34 #include "InjectedBundleRangeHandle.h"
35 #include "InjectedBundleScriptWorld.h"
36 #include "NetworkConnectionToWebProcessMessages.h"
37 #include "NetworkProcessConnection.h"
38 #include "PluginView.h"
39 #include "WKAPICast.h"
40 #include "WKBundleAPICast.h"
41 #include "WebChromeClient.h"
42 #include "WebCoreArgumentCoders.h"
43 #include "WebDocumentLoader.h"
44 #include "WebPage.h"
45 #include "WebPageProxyMessages.h"
46 #include "WebProcess.h"
47 #include <JavaScriptCore/APICast.h>
48 #include <JavaScriptCore/JSContextRef.h>
49 #include <JavaScriptCore/JSLock.h>
50 #include <JavaScriptCore/JSValueRef.h>
51 #include <WebCore/ArchiveResource.h>
52 #include <WebCore/CertificateInfo.h>
53 #include <WebCore/Chrome.h>
54 #include <WebCore/DocumentLoader.h>
55 #include <WebCore/EventHandler.h>
56 #include <WebCore/File.h>
57 #include <WebCore/Frame.h>
58 #include <WebCore/FrameSnapshotting.h>
59 #include <WebCore/FrameView.h>
60 #include <WebCore/HTMLFormElement.h>
61 #include <WebCore/HTMLFrameOwnerElement.h>
62 #include <WebCore/HTMLInputElement.h>
63 #include <WebCore/HTMLNames.h>
64 #include <WebCore/HTMLTextAreaElement.h>
65 #include <WebCore/ImageBuffer.h>
66 #include <WebCore/JSCSSStyleDeclaration.h>
67 #include <WebCore/JSElement.h>
68 #include <WebCore/JSFile.h>
69 #include <WebCore/JSRange.h>
70 #include <WebCore/MainFrame.h>
71 #include <WebCore/NetworkingContext.h>
72 #include <WebCore/NodeTraversal.h>
73 #include <WebCore/Page.h>
74 #include <WebCore/PluginDocument.h>
75 #include <WebCore/RenderTreeAsText.h>
76 #include <WebCore/ScriptController.h>
77 #include <WebCore/SecurityOrigin.h>
78 #include <WebCore/SubresourceLoader.h>
79 #include <WebCore/TextIterator.h>
80 #include <WebCore/TextResourceDecoder.h>
81 #include <wtf/text/StringBuilder.h>
82
83 #if PLATFORM(COCOA)
84 #include <WebCore/LegacyWebArchive.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::createWithCoreMainFrame(WebPage* page, WebCore::Frame* coreFrame)
111 {
112     RefPtr<WebFrame> frame = create(std::unique_ptr<WebFrameLoaderClient>(static_cast<WebFrameLoaderClient*>(&coreFrame->loader().client())));
113     page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID()), page->pageID(), IPC::DispatchMessageEvenWhenWaitingForSyncReply);
114
115     frame->m_coreFrame = coreFrame;
116     frame->m_coreFrame->tree().setName(String());
117     frame->m_coreFrame->init();
118     return frame.release();
119 }
120
121 PassRefPtr<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
122 {
123     RefPtr<WebFrame> frame = create(std::make_unique<WebFrameLoaderClient>());
124     page->send(Messages::WebPageProxy::DidCreateSubframe(frame->frameID()), page->pageID(), IPC::DispatchMessageEvenWhenWaitingForSyncReply);
125
126     Ref<WebCore::Frame> coreFrame = Frame::create(page->corePage(), ownerElement, frame->m_frameLoaderClient.get());
127     frame->m_coreFrame = coreFrame.ptr();
128     frame->m_coreFrame->tree().setName(frameName);
129     if (ownerElement) {
130         ASSERT(ownerElement->document().frame());
131         ownerElement->document().frame()->tree().appendChild(WTF::move(coreFrame));
132     }
133     frame->m_coreFrame->init();
134     return frame.release();
135 }
136
137 PassRefPtr<WebFrame> WebFrame::create(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient)
138 {
139     RefPtr<WebFrame> frame = adoptRef(new WebFrame(WTF::move(frameLoaderClient)));
140
141     // Add explict ref() that will be balanced in WebFrameLoaderClient::frameLoaderDestroyed().
142     frame->ref();
143
144     return frame.release();
145 }
146
147 WebFrame::WebFrame(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient)
148     : m_coreFrame(0)
149     , m_policyListenerID(0)
150     , m_policyFunction(0)
151     , m_policyDownloadID(0)
152     , m_frameLoaderClient(WTF::move(frameLoaderClient))
153     , m_loadListener(0)
154     , m_frameID(generateFrameID())
155 #if PLATFORM(IOS)
156     , m_firstLayerTreeTransactionIDAfterDidCommitLoad(0)
157 #endif
158 {
159     m_frameLoaderClient->setWebFrame(this);
160     WebProcess::singleton().addWebFrame(m_frameID, this);
161
162 #ifndef NDEBUG
163     webFrameCounter.increment();
164 #endif
165 }
166
167 WebFrame::~WebFrame()
168 {
169     ASSERT(!m_coreFrame);
170
171 #ifndef NDEBUG
172     webFrameCounter.decrement();
173 #endif
174 }
175
176 WebPage* WebFrame::page() const
177
178     if (!m_coreFrame)
179         return 0;
180     
181     if (Page* page = m_coreFrame->page())
182         return WebPage::fromCorePage(page);
183
184     return 0;
185 }
186
187 WebFrame* WebFrame::fromCoreFrame(Frame& frame)
188 {
189     auto* webFrameLoaderClient = toWebFrameLoaderClient(frame.loader().client());
190     if (!webFrameLoaderClient)
191         return nullptr;
192
193     return webFrameLoaderClient->webFrame();
194 }
195
196 void WebFrame::invalidate()
197 {
198     WebProcess::singleton().removeWebFrame(m_frameID);
199     m_coreFrame = 0;
200 }
201
202 uint64_t WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction policyFunction)
203 {
204     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
205
206     invalidatePolicyListener();
207
208     m_policyListenerID = generateListenerID();
209     m_policyFunction = policyFunction;
210     return m_policyListenerID;
211 }
212
213 void WebFrame::invalidatePolicyListener()
214 {
215     if (!m_policyListenerID)
216         return;
217
218     m_policyDownloadID = 0;
219     m_policyListenerID = 0;
220     m_policyFunction = 0;
221 }
222
223 void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action, uint64_t navigationID, uint64_t downloadID)
224 {
225     if (!m_coreFrame)
226         return;
227
228     if (!m_policyListenerID)
229         return;
230
231     if (listenerID != m_policyListenerID)
232         return;
233
234     ASSERT(m_policyFunction);
235
236     FramePolicyFunction function = WTF::move(m_policyFunction);
237
238     invalidatePolicyListener();
239
240     m_policyDownloadID = downloadID;
241     if (navigationID) {
242         if (WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(m_coreFrame->loader().policyDocumentLoader()))
243             documentLoader->setNavigationID(navigationID);
244     }
245
246     function(action);
247 }
248
249 void WebFrame::startDownload(const WebCore::ResourceRequest& request)
250 {
251     ASSERT(m_policyDownloadID);
252
253     uint64_t policyDownloadID = m_policyDownloadID;
254     m_policyDownloadID = 0;
255
256     auto& webProcess = WebProcess::singleton();
257     SessionID sessionID = page() ? page()->sessionID() : SessionID::defaultSessionID();
258     webProcess.networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::StartDownload(sessionID, policyDownloadID, request), 0);
259 }
260
261 void WebFrame::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, SessionID sessionID, const ResourceRequest& request, const ResourceResponse& response)
262 {
263     ASSERT(m_policyDownloadID);
264
265     uint64_t policyDownloadID = m_policyDownloadID;
266     m_policyDownloadID = 0;
267
268     SubresourceLoader* mainResourceLoader = documentLoader->mainResourceLoader();
269
270     auto& webProcess = WebProcess::singleton();
271     // Use 0 to indicate that the resource load can't be converted and a new download must be started.
272     // This can happen if there is no loader because the main resource is in the WebCore memory cache,
273     // or because the conversion was attempted when not calling SubresourceLoader::didReceiveResponse().
274     uint64_t mainResourceLoadIdentifier;
275     if (mainResourceLoader)
276         mainResourceLoadIdentifier = mainResourceLoader->identifier();
277     else
278         mainResourceLoadIdentifier = 0;
279
280     webProcess.networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::ConvertMainResourceLoadToDownload(sessionID, mainResourceLoadIdentifier, policyDownloadID, request, response), 0);
281 }
282
283 String WebFrame::source() const
284 {
285     if (!m_coreFrame)
286         return String();
287     Document* document = m_coreFrame->document();
288     if (!document)
289         return String();
290     TextResourceDecoder* decoder = document->decoder();
291     if (!decoder)
292         return String();
293     DocumentLoader* documentLoader = m_coreFrame->loader().activeDocumentLoader();
294     if (!documentLoader)
295         return String();
296     RefPtr<SharedBuffer> mainResourceData = documentLoader->mainResourceData();
297     if (!mainResourceData)
298         return String();
299     return decoder->encoding().decode(mainResourceData->data(), mainResourceData->size());
300 }
301
302 String WebFrame::contentsAsString() const 
303 {
304     if (!m_coreFrame)
305         return String();
306
307     if (isFrameSet()) {
308         StringBuilder builder;
309         for (Frame* child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
310             if (!builder.isEmpty())
311                 builder.append(' ');
312
313             WebFrame* webFrame = WebFrame::fromCoreFrame(*child);
314             ASSERT(webFrame);
315
316             builder.append(webFrame->contentsAsString());
317         }
318         // FIXME: It may make sense to use toStringPreserveCapacity() here.
319         return builder.toString();
320     }
321
322     Document* document = m_coreFrame->document();
323     if (!document)
324         return String();
325
326     RefPtr<Element> documentElement = document->documentElement();
327     if (!documentElement)
328         return String();
329
330     RefPtr<Range> range = document->createRange();
331
332     ExceptionCode ec = 0;
333     range->selectNode(documentElement.get(), ec);
334     if (ec)
335         return String();
336
337     return plainText(range.get());
338 }
339
340 String WebFrame::selectionAsString() const 
341 {
342     if (!m_coreFrame)
343         return String();
344
345     return m_coreFrame->displayStringModifiedByEncoding(m_coreFrame->editor().selectedText());
346 }
347
348 IntSize WebFrame::size() const
349 {
350     if (!m_coreFrame)
351         return IntSize();
352
353     FrameView* frameView = m_coreFrame->view();
354     if (!frameView)
355         return IntSize();
356
357     return frameView->contentsSize();
358 }
359
360 bool WebFrame::isFrameSet() const
361 {
362     if (!m_coreFrame)
363         return false;
364
365     Document* document = m_coreFrame->document();
366     if (!document)
367         return false;
368     return document->isFrameSet();
369 }
370
371 bool WebFrame::isMainFrame() const
372 {
373     if (!m_coreFrame)
374         return false;
375
376     return m_coreFrame->isMainFrame();
377 }
378
379 String WebFrame::name() const
380 {
381     if (!m_coreFrame)
382         return String();
383
384     return m_coreFrame->tree().uniqueName();
385 }
386
387 String WebFrame::url() const
388 {
389     if (!m_coreFrame)
390         return String();
391
392     DocumentLoader* documentLoader = m_coreFrame->loader().documentLoader();
393     if (!documentLoader)
394         return String();
395
396     return documentLoader->url().string();
397 }
398
399 WebCore::CertificateInfo WebFrame::certificateInfo() const
400 {
401     if (!m_coreFrame)
402         return CertificateInfo();
403
404     DocumentLoader* documentLoader = m_coreFrame->loader().documentLoader();
405     if (!documentLoader)
406         return CertificateInfo();
407
408     return documentLoader->response().certificateInfo();
409 }
410
411 String WebFrame::innerText() const
412 {
413     if (!m_coreFrame)
414         return String();
415
416     if (!m_coreFrame->document()->documentElement())
417         return String();
418
419     return m_coreFrame->document()->documentElement()->innerText();
420 }
421
422 WebFrame* WebFrame::parentFrame() const
423 {
424     if (!m_coreFrame || !m_coreFrame->ownerElement())
425         return 0;
426
427     return WebFrame::fromCoreFrame(*m_coreFrame->ownerElement()->document().frame());
428 }
429
430 Ref<API::Array> WebFrame::childFrames()
431 {
432     if (!m_coreFrame)
433         return API::Array::create();
434
435     size_t size = m_coreFrame->tree().childCount();
436     if (!size)
437         return API::Array::create();
438
439     Vector<RefPtr<API::Object>> vector;
440     vector.reserveInitialCapacity(size);
441
442     for (Frame* child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
443         WebFrame* webFrame = WebFrame::fromCoreFrame(*child);
444         ASSERT(webFrame);
445         vector.uncheckedAppend(webFrame);
446     }
447
448     return API::Array::create(WTF::move(vector));
449 }
450
451 String WebFrame::layerTreeAsText() const
452 {
453     if (!m_coreFrame)
454         return "";
455
456     return m_coreFrame->layerTreeAsText(0);
457 }
458
459 unsigned WebFrame::pendingUnloadCount() const
460 {
461     if (!m_coreFrame)
462         return 0;
463
464     return m_coreFrame->document()->domWindow()->pendingUnloadEventListeners();
465 }
466
467 bool WebFrame::allowsFollowingLink(const WebCore::URL& url) const
468 {
469     if (!m_coreFrame)
470         return true;
471         
472     return m_coreFrame->document()->securityOrigin()->canDisplay(url);
473 }
474
475 JSGlobalContextRef WebFrame::jsContext()
476 {
477     return toGlobalRef(m_coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec());
478 }
479
480 JSGlobalContextRef WebFrame::jsContextForWorld(InjectedBundleScriptWorld* world)
481 {
482     return toGlobalRef(m_coreFrame->script().globalObject(world->coreWorld())->globalExec());
483 }
484
485 bool WebFrame::handlesPageScaleGesture() const
486 {
487     if (!m_coreFrame->document()->isPluginDocument())
488         return 0;
489
490     PluginDocument* pluginDocument = static_cast<PluginDocument*>(m_coreFrame->document());
491     PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
492     return pluginView && pluginView->handlesPageScaleFactor();
493 }
494
495 bool WebFrame::requiresUnifiedScaleFactor() const
496 {
497     if (!m_coreFrame->document()->isPluginDocument())
498         return 0;
499
500     PluginDocument* pluginDocument = static_cast<PluginDocument*>(m_coreFrame->document());
501     PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
502     return pluginView && pluginView->requiresUnifiedScaleFactor();
503 }
504
505 void WebFrame::setAccessibleName(const String& accessibleName)
506 {
507     if (!AXObjectCache::accessibilityEnabled())
508         return;
509     
510     if (!m_coreFrame)
511         return;
512
513     auto* document = m_coreFrame->document();
514     if (!document)
515         return;
516     
517     auto* rootObject = document->axObjectCache()->rootObject();
518     if (!rootObject)
519         return;
520
521     rootObject->setAccessibleName(accessibleName);
522 }
523
524 IntRect WebFrame::contentBounds() const
525 {    
526     if (!m_coreFrame)
527         return IntRect();
528     
529     FrameView* view = m_coreFrame->view();
530     if (!view)
531         return IntRect();
532     
533     return IntRect(0, 0, view->contentsWidth(), view->contentsHeight());
534 }
535
536 IntRect WebFrame::visibleContentBounds() const
537 {
538     if (!m_coreFrame)
539         return IntRect();
540     
541     FrameView* view = m_coreFrame->view();
542     if (!view)
543         return IntRect();
544     
545     IntRect contentRect = view->visibleContentRectIncludingScrollbars();
546     return IntRect(0, 0, contentRect.width(), contentRect.height());
547 }
548
549 IntRect WebFrame::visibleContentBoundsExcludingScrollbars() const
550 {
551     if (!m_coreFrame)
552         return IntRect();
553     
554     FrameView* view = m_coreFrame->view();
555     if (!view)
556         return IntRect();
557     
558     IntRect contentRect = view->visibleContentRect();
559     return IntRect(0, 0, contentRect.width(), contentRect.height());
560 }
561
562 IntSize WebFrame::scrollOffset() const
563 {
564     if (!m_coreFrame)
565         return IntSize();
566     
567     FrameView* view = m_coreFrame->view();
568     if (!view)
569         return IntSize();
570
571     return view->scrollOffset();
572 }
573
574 bool WebFrame::hasHorizontalScrollbar() const
575 {
576     if (!m_coreFrame)
577         return false;
578
579     FrameView* view = m_coreFrame->view();
580     if (!view)
581         return false;
582
583     return view->horizontalScrollbar();
584 }
585
586 bool WebFrame::hasVerticalScrollbar() const
587 {
588     if (!m_coreFrame)
589         return false;
590
591     FrameView* view = m_coreFrame->view();
592     if (!view)
593         return false;
594
595     return view->verticalScrollbar();
596 }
597
598 PassRefPtr<InjectedBundleHitTestResult> WebFrame::hitTest(const IntPoint point) const
599 {
600     if (!m_coreFrame)
601         return 0;
602
603     return InjectedBundleHitTestResult::create(m_coreFrame->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent));
604 }
605
606 bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha)
607 {
608     if (!m_coreFrame)
609         return false;
610
611     FrameView* view = m_coreFrame->view();
612     if (!view)
613         return false;
614
615     Color bgColor = view->documentBackgroundColor();
616     if (!bgColor.isValid())
617         return false;
618
619     bgColor.getRGBA(*red, *green, *blue, *alpha);
620     return true;
621 }
622
623 bool WebFrame::containsAnyFormElements() const
624 {
625     if (!m_coreFrame)
626         return false;
627     
628     Document* document = m_coreFrame->document();
629     if (!document)
630         return false;
631
632     for (Node* node = document->documentElement(); node; node = NodeTraversal::next(*node)) {
633         if (!is<Element>(*node))
634             continue;
635         if (is<HTMLFormElement>(*node))
636             return true;
637     }
638     return false;
639 }
640
641 bool WebFrame::containsAnyFormControls() const
642 {
643     if (!m_coreFrame)
644         return false;
645     
646     Document* document = m_coreFrame->document();
647     if (!document)
648         return false;
649
650     for (Node* node = document->documentElement(); node; node = NodeTraversal::next(*node)) {
651         if (!is<Element>(*node))
652             continue;
653         if (is<HTMLInputElement>(*node) || is<HTMLSelectElement>(*node) || is<HTMLTextAreaElement>(*node))
654             return true;
655     }
656     return false;
657 }
658
659 void WebFrame::stopLoading()
660 {
661     if (!m_coreFrame)
662         return;
663
664     m_coreFrame->loader().stopForUserCancel();
665 }
666
667 WebFrame* WebFrame::frameForContext(JSContextRef context)
668 {
669     JSObjectRef globalObjectRef = JSContextGetGlobalObject(context);
670     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
671     if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0)
672         return 0;
673
674     Frame* frame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->wrapped().frame();
675     return WebFrame::fromCoreFrame(*frame);
676 }
677
678 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world)
679 {
680     if (!m_coreFrame)
681         return 0;
682
683     JSDOMWindow* globalObject = m_coreFrame->script().globalObject(world->coreWorld());
684     ExecState* exec = globalObject->globalExec();
685
686     JSLockHolder lock(exec);
687     return toRef(exec, toJS(exec, globalObject, nodeHandle->coreNode()));
688 }
689
690 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleRangeHandle* rangeHandle, InjectedBundleScriptWorld* world)
691 {
692     if (!m_coreFrame)
693         return 0;
694
695     JSDOMWindow* globalObject = m_coreFrame->script().globalObject(world->coreWorld());
696     ExecState* exec = globalObject->globalExec();
697
698     JSLockHolder lock(exec);
699     return toRef(exec, toJS(exec, globalObject, rangeHandle->coreRange()));
700 }
701
702 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleFileHandle* fileHandle, InjectedBundleScriptWorld* world)
703 {
704     if (!m_coreFrame)
705         return nullptr;
706
707     JSDOMWindow* globalObject = m_coreFrame->script().globalObject(world->coreWorld());
708     ExecState* exec = globalObject->globalExec();
709
710     JSLockHolder lock(exec);
711     return toRef(exec, toJS(exec, globalObject, fileHandle->coreFile()));
712 }
713
714 String WebFrame::counterValue(JSObjectRef element)
715 {
716     if (!toJS(element)->inherits(JSElement::info()))
717         return String();
718
719     return counterValueForElement(&jsCast<JSElement*>(toJS(element))->wrapped());
720 }
721
722 String WebFrame::provisionalURL() const
723 {
724     if (!m_coreFrame)
725         return String();
726
727     DocumentLoader* provisionalDocumentLoader = m_coreFrame->loader().provisionalDocumentLoader();
728     if (!provisionalDocumentLoader)
729         return String();
730
731     return provisionalDocumentLoader->url().string();
732 }
733
734 String WebFrame::suggestedFilenameForResourceWithURL(const URL& url) const
735 {
736     if (!m_coreFrame)
737         return String();
738
739     DocumentLoader* loader = m_coreFrame->loader().documentLoader();
740     if (!loader)
741         return String();
742
743     // First, try the main resource.
744     if (loader->url() == url)
745         return loader->response().suggestedFilename();
746
747     // Next, try subresources.
748     RefPtr<ArchiveResource> resource = loader->subresource(url);
749     if (resource)
750         return resource->response().suggestedFilename();
751
752     return page()->cachedSuggestedFilenameForURL(url);
753 }
754
755 String WebFrame::mimeTypeForResourceWithURL(const URL& url) const
756 {
757     if (!m_coreFrame)
758         return String();
759
760     DocumentLoader* loader = m_coreFrame->loader().documentLoader();
761     if (!loader)
762         return String();
763
764     // First, try the main resource.
765     if (loader->url() == url)
766         return loader->response().mimeType();
767
768     // Next, try subresources.
769     RefPtr<ArchiveResource> resource = loader->subresource(url);
770     if (resource)
771         return resource->mimeType();
772
773     return page()->cachedResponseMIMETypeForURL(url);
774 }
775
776 void WebFrame::setTextDirection(const String& direction)
777 {
778     if (!m_coreFrame)
779         return;
780
781     if (direction == "auto")
782         m_coreFrame->editor().setBaseWritingDirection(NaturalWritingDirection);
783     else if (direction == "ltr")
784         m_coreFrame->editor().setBaseWritingDirection(LeftToRightWritingDirection);
785     else if (direction == "rtl")
786         m_coreFrame->editor().setBaseWritingDirection(RightToLeftWritingDirection);
787 }
788
789 void WebFrame::documentLoaderDetached(uint64_t navigationID)
790 {
791     page()->send(Messages::WebPageProxy::DidDestroyNavigation(navigationID));
792 }
793
794 #if PLATFORM(COCOA)
795 RetainPtr<CFDataRef> WebFrame::webArchiveData(FrameFilterFunction callback, void* context)
796 {
797     RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(coreFrame()->document(), [this, callback, context](Frame& frame) -> bool {
798         if (!callback)
799             return true;
800
801         WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
802         ASSERT(webFrame);
803
804         return callback(toAPI(this), toAPI(webFrame), context);
805     });
806
807     if (!archive)
808         return nullptr;
809
810     return archive->rawDataRepresentation();
811 }
812 #endif
813
814 PassRefPtr<ShareableBitmap> WebFrame::createSelectionSnapshot() const
815 {
816     std::unique_ptr<ImageBuffer> snapshot = snapshotSelection(*coreFrame(), WebCore::SnapshotOptionsForceBlackText);
817     if (!snapshot)
818         return nullptr;
819
820     RefPtr<ShareableBitmap> sharedSnapshot = ShareableBitmap::createShareable(snapshot->internalSize(), ShareableBitmap::SupportsAlpha);
821     if (!sharedSnapshot)
822         return nullptr;
823
824     // FIXME: We should consider providing a way to use subpixel antialiasing for the snapshot
825     // if we're compositing this image onto a solid color (e.g. the modern find indicator style).
826     auto graphicsContext = sharedSnapshot->createGraphicsContext();
827     float deviceScaleFactor = coreFrame()->page()->deviceScaleFactor();
828     graphicsContext->scale(FloatSize(deviceScaleFactor, deviceScaleFactor));
829     graphicsContext->drawConsumingImageBuffer(WTF::move(snapshot), FloatPoint());
830
831     return sharedSnapshot.release();
832 }
833     
834 } // namespace WebKit