5381b753bbcac500fd6533e7091ec48d5e26c96f
[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     if (range->selectNode(*documentElement).hasException())
348         return String();
349
350     return plainText(range.get());
351 }
352
353 String WebFrame::selectionAsString() const 
354 {
355     if (!m_coreFrame)
356         return String();
357
358     return m_coreFrame->displayStringModifiedByEncoding(m_coreFrame->editor().selectedText());
359 }
360
361 IntSize WebFrame::size() const
362 {
363     if (!m_coreFrame)
364         return IntSize();
365
366     FrameView* frameView = m_coreFrame->view();
367     if (!frameView)
368         return IntSize();
369
370     return frameView->contentsSize();
371 }
372
373 bool WebFrame::isFrameSet() const
374 {
375     if (!m_coreFrame)
376         return false;
377
378     Document* document = m_coreFrame->document();
379     if (!document)
380         return false;
381     return document->isFrameSet();
382 }
383
384 bool WebFrame::isMainFrame() const
385 {
386     if (!m_coreFrame)
387         return false;
388
389     return m_coreFrame->isMainFrame();
390 }
391
392 String WebFrame::name() const
393 {
394     if (!m_coreFrame)
395         return String();
396
397     return m_coreFrame->tree().uniqueName();
398 }
399
400 String WebFrame::url() const
401 {
402     if (!m_coreFrame)
403         return String();
404
405     DocumentLoader* documentLoader = m_coreFrame->loader().documentLoader();
406     if (!documentLoader)
407         return String();
408
409     return documentLoader->url().string();
410 }
411
412 CertificateInfo WebFrame::certificateInfo() const
413 {
414     if (!m_coreFrame)
415         return { };
416
417     DocumentLoader* documentLoader = m_coreFrame->loader().documentLoader();
418     if (!documentLoader)
419         return { };
420
421     return valueOrCompute(documentLoader->response().certificateInfo(), [] { return CertificateInfo(); });
422 }
423
424 String WebFrame::innerText() const
425 {
426     if (!m_coreFrame)
427         return String();
428
429     if (!m_coreFrame->document()->documentElement())
430         return String();
431
432     return m_coreFrame->document()->documentElement()->innerText();
433 }
434
435 WebFrame* WebFrame::parentFrame() const
436 {
437     if (!m_coreFrame || !m_coreFrame->ownerElement())
438         return 0;
439
440     return WebFrame::fromCoreFrame(*m_coreFrame->ownerElement()->document().frame());
441 }
442
443 Ref<API::Array> WebFrame::childFrames()
444 {
445     if (!m_coreFrame)
446         return API::Array::create();
447
448     size_t size = m_coreFrame->tree().childCount();
449     if (!size)
450         return API::Array::create();
451
452     Vector<RefPtr<API::Object>> vector;
453     vector.reserveInitialCapacity(size);
454
455     for (Frame* child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
456         WebFrame* webFrame = WebFrame::fromCoreFrame(*child);
457         ASSERT(webFrame);
458         vector.uncheckedAppend(webFrame);
459     }
460
461     return API::Array::create(WTFMove(vector));
462 }
463
464 String WebFrame::layerTreeAsText() const
465 {
466     if (!m_coreFrame)
467         return "";
468
469     return m_coreFrame->layerTreeAsText(0);
470 }
471
472 unsigned WebFrame::pendingUnloadCount() const
473 {
474     if (!m_coreFrame)
475         return 0;
476
477     return m_coreFrame->document()->domWindow()->pendingUnloadEventListeners();
478 }
479
480 bool WebFrame::allowsFollowingLink(const WebCore::URL& url) const
481 {
482     if (!m_coreFrame)
483         return true;
484         
485     return m_coreFrame->document()->securityOrigin()->canDisplay(url);
486 }
487
488 JSGlobalContextRef WebFrame::jsContext()
489 {
490     return toGlobalRef(m_coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec());
491 }
492
493 JSGlobalContextRef WebFrame::jsContextForWorld(InjectedBundleScriptWorld* world)
494 {
495     return toGlobalRef(m_coreFrame->script().globalObject(world->coreWorld())->globalExec());
496 }
497
498 bool WebFrame::handlesPageScaleGesture() const
499 {
500     if (!m_coreFrame->document()->isPluginDocument())
501         return 0;
502
503     PluginDocument* pluginDocument = static_cast<PluginDocument*>(m_coreFrame->document());
504     PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
505     return pluginView && pluginView->handlesPageScaleFactor();
506 }
507
508 bool WebFrame::requiresUnifiedScaleFactor() const
509 {
510     if (!m_coreFrame->document()->isPluginDocument())
511         return 0;
512
513     PluginDocument* pluginDocument = static_cast<PluginDocument*>(m_coreFrame->document());
514     PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
515     return pluginView && pluginView->requiresUnifiedScaleFactor();
516 }
517
518 void WebFrame::setAccessibleName(const String& accessibleName)
519 {
520     if (!AXObjectCache::accessibilityEnabled())
521         return;
522     
523     if (!m_coreFrame)
524         return;
525
526     auto* document = m_coreFrame->document();
527     if (!document)
528         return;
529     
530     auto* rootObject = document->axObjectCache()->rootObject();
531     if (!rootObject)
532         return;
533
534     rootObject->setAccessibleName(accessibleName);
535 }
536
537 IntRect WebFrame::contentBounds() const
538 {    
539     if (!m_coreFrame)
540         return IntRect();
541     
542     FrameView* view = m_coreFrame->view();
543     if (!view)
544         return IntRect();
545     
546     return IntRect(0, 0, view->contentsWidth(), view->contentsHeight());
547 }
548
549 IntRect WebFrame::visibleContentBounds() 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->visibleContentRectIncludingScrollbars();
559     return IntRect(0, 0, contentRect.width(), contentRect.height());
560 }
561
562 IntRect WebFrame::visibleContentBoundsExcludingScrollbars() const
563 {
564     if (!m_coreFrame)
565         return IntRect();
566     
567     FrameView* view = m_coreFrame->view();
568     if (!view)
569         return IntRect();
570     
571     IntRect contentRect = view->visibleContentRect();
572     return IntRect(0, 0, contentRect.width(), contentRect.height());
573 }
574
575 IntSize WebFrame::scrollOffset() const
576 {
577     if (!m_coreFrame)
578         return IntSize();
579     
580     FrameView* view = m_coreFrame->view();
581     if (!view)
582         return IntSize();
583
584     return toIntSize(view->scrollPosition());
585 }
586
587 bool WebFrame::hasHorizontalScrollbar() const
588 {
589     if (!m_coreFrame)
590         return false;
591
592     FrameView* view = m_coreFrame->view();
593     if (!view)
594         return false;
595
596     return view->horizontalScrollbar();
597 }
598
599 bool WebFrame::hasVerticalScrollbar() 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->verticalScrollbar();
609 }
610
611 PassRefPtr<InjectedBundleHitTestResult> WebFrame::hitTest(const IntPoint point) const
612 {
613     if (!m_coreFrame)
614         return 0;
615
616     return InjectedBundleHitTestResult::create(m_coreFrame->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent));
617 }
618
619 bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha)
620 {
621     if (!m_coreFrame)
622         return false;
623
624     FrameView* view = m_coreFrame->view();
625     if (!view)
626         return false;
627
628     Color bgColor = view->documentBackgroundColor();
629     if (!bgColor.isValid())
630         return false;
631
632     bgColor.getRGBA(*red, *green, *blue, *alpha);
633     return true;
634 }
635
636 bool WebFrame::containsAnyFormElements() const
637 {
638     if (!m_coreFrame)
639         return false;
640     
641     Document* document = m_coreFrame->document();
642     if (!document)
643         return false;
644
645     for (Node* node = document->documentElement(); node; node = NodeTraversal::next(*node)) {
646         if (!is<Element>(*node))
647             continue;
648         if (is<HTMLFormElement>(*node))
649             return true;
650     }
651     return false;
652 }
653
654 bool WebFrame::containsAnyFormControls() const
655 {
656     if (!m_coreFrame)
657         return false;
658     
659     Document* document = m_coreFrame->document();
660     if (!document)
661         return false;
662
663     for (Node* node = document->documentElement(); node; node = NodeTraversal::next(*node)) {
664         if (!is<Element>(*node))
665             continue;
666         if (is<HTMLInputElement>(*node) || is<HTMLSelectElement>(*node) || is<HTMLTextAreaElement>(*node))
667             return true;
668     }
669     return false;
670 }
671
672 void WebFrame::stopLoading()
673 {
674     if (!m_coreFrame)
675         return;
676
677     m_coreFrame->loader().stopForUserCancel();
678 }
679
680 WebFrame* WebFrame::frameForContext(JSContextRef context)
681 {
682     JSObjectRef globalObjectRef = JSContextGetGlobalObject(context);
683     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
684     if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0)
685         return 0;
686
687     Frame* frame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->wrapped().frame();
688     return WebFrame::fromCoreFrame(*frame);
689 }
690
691 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world)
692 {
693     if (!m_coreFrame)
694         return 0;
695
696     JSDOMWindow* globalObject = m_coreFrame->script().globalObject(world->coreWorld());
697     ExecState* exec = globalObject->globalExec();
698
699     JSLockHolder lock(exec);
700     return toRef(exec, toJS(exec, globalObject, nodeHandle->coreNode()));
701 }
702
703 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleRangeHandle* rangeHandle, InjectedBundleScriptWorld* world)
704 {
705     if (!m_coreFrame)
706         return 0;
707
708     JSDOMWindow* globalObject = m_coreFrame->script().globalObject(world->coreWorld());
709     ExecState* exec = globalObject->globalExec();
710
711     JSLockHolder lock(exec);
712     return toRef(exec, toJS(exec, globalObject, rangeHandle->coreRange()));
713 }
714
715 JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleFileHandle* fileHandle, InjectedBundleScriptWorld* world)
716 {
717     if (!m_coreFrame)
718         return nullptr;
719
720     JSDOMWindow* globalObject = m_coreFrame->script().globalObject(world->coreWorld());
721     ExecState* exec = globalObject->globalExec();
722
723     JSLockHolder lock(exec);
724     return toRef(exec, toJS(exec, globalObject, fileHandle->coreFile()));
725 }
726
727 String WebFrame::counterValue(JSObjectRef element)
728 {
729     if (!toJS(element)->inherits(JSElement::info()))
730         return String();
731
732     return counterValueForElement(&jsCast<JSElement*>(toJS(element))->wrapped());
733 }
734
735 String WebFrame::provisionalURL() const
736 {
737     if (!m_coreFrame)
738         return String();
739
740     DocumentLoader* provisionalDocumentLoader = m_coreFrame->loader().provisionalDocumentLoader();
741     if (!provisionalDocumentLoader)
742         return String();
743
744     return provisionalDocumentLoader->url().string();
745 }
746
747 String WebFrame::suggestedFilenameForResourceWithURL(const URL& url) const
748 {
749     if (!m_coreFrame)
750         return String();
751
752     DocumentLoader* loader = m_coreFrame->loader().documentLoader();
753     if (!loader)
754         return String();
755
756     // First, try the main resource.
757     if (loader->url() == url)
758         return loader->response().suggestedFilename();
759
760     // Next, try subresources.
761     RefPtr<ArchiveResource> resource = loader->subresource(url);
762     if (resource)
763         return resource->response().suggestedFilename();
764
765     return page()->cachedSuggestedFilenameForURL(url);
766 }
767
768 String WebFrame::mimeTypeForResourceWithURL(const URL& url) const
769 {
770     if (!m_coreFrame)
771         return String();
772
773     DocumentLoader* loader = m_coreFrame->loader().documentLoader();
774     if (!loader)
775         return String();
776
777     // First, try the main resource.
778     if (loader->url() == url)
779         return loader->response().mimeType();
780
781     // Next, try subresources.
782     RefPtr<ArchiveResource> resource = loader->subresource(url);
783     if (resource)
784         return resource->mimeType();
785
786     return page()->cachedResponseMIMETypeForURL(url);
787 }
788
789 void WebFrame::setTextDirection(const String& direction)
790 {
791     if (!m_coreFrame)
792         return;
793
794     if (direction == "auto")
795         m_coreFrame->editor().setBaseWritingDirection(NaturalWritingDirection);
796     else if (direction == "ltr")
797         m_coreFrame->editor().setBaseWritingDirection(LeftToRightWritingDirection);
798     else if (direction == "rtl")
799         m_coreFrame->editor().setBaseWritingDirection(RightToLeftWritingDirection);
800 }
801
802 void WebFrame::documentLoaderDetached(uint64_t navigationID)
803 {
804     page()->send(Messages::WebPageProxy::DidDestroyNavigation(navigationID));
805 }
806
807 #if PLATFORM(COCOA)
808 RetainPtr<CFDataRef> WebFrame::webArchiveData(FrameFilterFunction callback, void* context)
809 {
810     RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(*coreFrame()->document(), [this, callback, context](Frame& frame) -> bool {
811         if (!callback)
812             return true;
813
814         WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
815         ASSERT(webFrame);
816
817         return callback(toAPI(this), toAPI(webFrame), context);
818     });
819
820     if (!archive)
821         return nullptr;
822
823     return archive->rawDataRepresentation();
824 }
825 #endif
826
827 PassRefPtr<ShareableBitmap> WebFrame::createSelectionSnapshot() const
828 {
829     std::unique_ptr<ImageBuffer> snapshot = snapshotSelection(*coreFrame(), WebCore::SnapshotOptionsForceBlackText);
830     if (!snapshot)
831         return nullptr;
832
833     auto sharedSnapshot = ShareableBitmap::createShareable(snapshot->internalSize(), ShareableBitmap::SupportsAlpha);
834     if (!sharedSnapshot)
835         return nullptr;
836
837     // FIXME: We should consider providing a way to use subpixel antialiasing for the snapshot
838     // if we're compositing this image onto a solid color (e.g. the modern find indicator style).
839     auto graphicsContext = sharedSnapshot->createGraphicsContext();
840     float deviceScaleFactor = coreFrame()->page()->deviceScaleFactor();
841     graphicsContext->scale(deviceScaleFactor);
842     graphicsContext->drawConsumingImageBuffer(WTFMove(snapshot), FloatPoint());
843
844     return WTFMove(sharedSnapshot);
845 }
846     
847 } // namespace WebKit