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