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