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