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