Reduce use of SessionID::defaultSessionID() in WebKit
[WebKit-https.git] / Source / WebKit / WebProcess / WebPage / WebFrame.cpp
1 /*
2  * Copyright (C) 2010-2019 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 generateListenerID()
99 {
100     static uint64_t uniqueListenerID = 1;
101     return uniqueListenerID++;
102 }
103
104 Ref<WebFrame> WebFrame::createWithCoreMainFrame(WebPage* page, WebCore::Frame* coreFrame)
105 {
106     auto frame = create(std::unique_ptr<WebFrameLoaderClient>(static_cast<WebFrameLoaderClient*>(&coreFrame->loader().client())));
107     page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID()));
108
109     frame->m_coreFrame = coreFrame;
110     frame->m_coreFrame->tree().setName(String());
111     frame->m_coreFrame->init();
112     return frame;
113 }
114
115 Ref<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
116 {
117     auto frame = create(makeUnique<WebFrameLoaderClient>());
118     page->send(Messages::WebPageProxy::DidCreateSubframe(frame->frameID()));
119
120     auto coreFrame = Frame::create(page->corePage(), ownerElement, frame->m_frameLoaderClient.get());
121     frame->m_coreFrame = coreFrame.ptr();
122
123     coreFrame->tree().setName(frameName);
124     if (ownerElement) {
125         ASSERT(ownerElement->document().frame());
126         ownerElement->document().frame()->tree().appendChild(coreFrame.get());
127     }
128     coreFrame->init();
129
130     return frame;
131 }
132
133 Ref<WebFrame> WebFrame::create(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient)
134 {
135     auto frame = adoptRef(*new WebFrame(WTFMove(frameLoaderClient)));
136
137     // Add explict ref() that will be balanced in WebFrameLoaderClient::frameLoaderDestroyed().
138     frame->ref();
139
140     return frame;
141 }
142
143 WebFrame::WebFrame(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient)
144     : m_frameLoaderClient(WTFMove(frameLoaderClient))
145     , m_frameID(FrameIdentifier::generate())
146 {
147     m_frameLoaderClient->setWebFrame(this);
148     WebProcess::singleton().addWebFrame(m_frameID, this);
149
150 #ifndef NDEBUG
151     webFrameCounter.increment();
152 #endif
153 }
154
155 WebFrame::~WebFrame()
156 {
157     ASSERT(!m_coreFrame);
158
159     auto willSubmitFormCompletionHandlers = WTFMove(m_willSubmitFormCompletionHandlers);
160     for (auto& completionHandler : willSubmitFormCompletionHandlers.values())
161         completionHandler();
162
163 #ifndef NDEBUG
164     webFrameCounter.decrement();
165 #endif
166 }
167
168 WebPage* WebFrame::page() const
169 {
170     if (!m_coreFrame)
171         return nullptr;
172     
173     if (auto* page = m_coreFrame->page())
174         return &WebPage::fromCorePage(*page);
175
176     return nullptr;
177 }
178
179 WebFrame* WebFrame::fromCoreFrame(Frame& frame)
180 {
181     auto* webFrameLoaderClient = toWebFrameLoaderClient(frame.loader().client());
182     if (!webFrameLoaderClient)
183         return nullptr;
184
185     return webFrameLoaderClient->webFrame();
186 }
187
188 FrameInfoData WebFrame::info() const
189 {
190     FrameInfoData info;
191
192     info.isMainFrame = isMainFrame();
193     // FIXME: This should use the full request.
194     info.request = ResourceRequest(URL(URL(), url()));
195     info.securityOrigin = SecurityOriginData::fromFrame(m_coreFrame);
196     info.frameID = m_frameID;
197     
198     return info;
199 }
200
201 void WebFrame::invalidate()
202 {
203     WebProcess::singleton().removeWebFrame(m_frameID);
204     m_coreFrame = 0;
205 }
206
207 uint64_t WebFrame::setUpPolicyListener(WebCore::PolicyCheckIdentifier identifier, WebCore::FramePolicyFunction&& policyFunction, ForNavigationAction forNavigationAction)
208 {
209     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
210
211     invalidatePolicyListener();
212
213     m_policyIdentifier = identifier;
214     m_policyListenerID = generateListenerID();
215     m_policyFunction = WTFMove(policyFunction);
216     m_policyFunctionForNavigationAction = forNavigationAction;
217     return m_policyListenerID;
218 }
219
220 uint64_t WebFrame::setUpWillSubmitFormListener(CompletionHandler<void()>&& completionHandler)
221 {
222     uint64_t identifier = generateListenerID();
223     invalidatePolicyListener();
224     m_willSubmitFormCompletionHandlers.set(identifier, WTFMove(completionHandler));
225     return identifier;
226 }
227
228 void WebFrame::continueWillSubmitForm(uint64_t listenerID)
229 {
230     Ref<WebFrame> protectedThis(*this);
231     if (auto completionHandler = m_willSubmitFormCompletionHandlers.take(listenerID))
232         completionHandler();
233     invalidatePolicyListener();
234 }
235
236 void WebFrame::invalidatePolicyListener()
237 {
238     if (!m_policyListenerID)
239         return;
240
241     m_policyDownloadID = { };
242     m_policyListenerID = 0;
243     auto identifier = m_policyIdentifier;
244     m_policyIdentifier = WTF::nullopt;
245     if (auto function = std::exchange(m_policyFunction, nullptr))
246         function(PolicyAction::Ignore, *identifier);
247     m_policyFunctionForNavigationAction = ForNavigationAction::No;
248
249     auto willSubmitFormCompletionHandlers = WTFMove(m_willSubmitFormCompletionHandlers);
250     for (auto& completionHandler : willSubmitFormCompletionHandlers.values())
251         completionHandler();
252 }
253
254 void WebFrame::didReceivePolicyDecision(uint64_t listenerID, WebCore::PolicyCheckIdentifier identifier, PolicyAction action, uint64_t navigationID, DownloadID downloadID, Optional<WebsitePoliciesData>&& websitePolicies)
255 {
256     if (!m_coreFrame || !m_policyListenerID || listenerID != m_policyListenerID || !m_policyFunction)
257         return;
258
259     ASSERT(identifier == m_policyIdentifier);
260     m_policyIdentifier = WTF::nullopt;
261
262     FramePolicyFunction function = WTFMove(m_policyFunction);
263     bool forNavigationAction = m_policyFunctionForNavigationAction == ForNavigationAction::Yes;
264
265     invalidatePolicyListener();
266
267     if (forNavigationAction && m_frameLoaderClient && websitePolicies)
268         m_frameLoaderClient->applyToDocumentLoader(WTFMove(*websitePolicies));
269
270     m_policyDownloadID = downloadID;
271     if (navigationID) {
272         if (WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(m_coreFrame->loader().policyDocumentLoader()))
273             documentLoader->setNavigationID(navigationID);
274     }
275
276     function(action, identifier);
277 }
278
279 void WebFrame::startDownload(const WebCore::ResourceRequest& request, const String& suggestedName)
280 {
281     ASSERT(m_policyDownloadID.downloadID());
282
283     auto policyDownloadID = m_policyDownloadID;
284     m_policyDownloadID = { };
285
286     WebProcess::singleton().ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::StartDownload(policyDownloadID, request, suggestedName), 0);
287 }
288
289 void WebFrame::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, const ResourceRequest& request, const ResourceResponse& response)
290 {
291     ASSERT(m_policyDownloadID.downloadID());
292
293     auto policyDownloadID = m_policyDownloadID;
294     m_policyDownloadID = { };
295
296     SubresourceLoader* mainResourceLoader = documentLoader->mainResourceLoader();
297
298     auto& webProcess = WebProcess::singleton();
299     // Use 0 to indicate that the resource load can't be converted and a new download must be started.
300     // This can happen if there is no loader because the main resource is in the WebCore memory cache,
301     // or because the conversion was attempted when not calling SubresourceLoader::didReceiveResponse().
302     uint64_t mainResourceLoadIdentifier;
303     if (mainResourceLoader)
304         mainResourceLoadIdentifier = mainResourceLoader->identifier();
305     else
306         mainResourceLoadIdentifier = 0;
307
308     webProcess.ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ConvertMainResourceLoadToDownload(mainResourceLoadIdentifier, policyDownloadID, request, response), 0);
309 }
310
311 void WebFrame::addConsoleMessage(MessageSource messageSource, MessageLevel messageLevel, const String& message, uint64_t requestID)
312 {
313     if (!m_coreFrame)
314         return;
315     if (auto* document = m_coreFrame->document())
316         document->addConsoleMessage(messageSource, messageLevel, message, requestID);
317 }
318
319 String WebFrame::source() const
320 {
321     if (!m_coreFrame)
322         return String();
323     Document* document = m_coreFrame->document();
324     if (!document)
325         return String();
326     TextResourceDecoder* decoder = document->decoder();
327     if (!decoder)
328         return String();
329     DocumentLoader* documentLoader = m_coreFrame->loader().activeDocumentLoader();
330     if (!documentLoader)
331         return String();
332     RefPtr<SharedBuffer> mainResourceData = documentLoader->mainResourceData();
333     if (!mainResourceData)
334         return String();
335     return decoder->encoding().decode(mainResourceData->data(), mainResourceData->size());
336 }
337
338 String WebFrame::contentsAsString() const 
339 {
340     if (!m_coreFrame)
341         return String();
342
343     if (isFrameSet()) {
344         StringBuilder builder;
345         for (Frame* child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
346             if (!builder.isEmpty())
347                 builder.append(' ');
348
349             WebFrame* webFrame = WebFrame::fromCoreFrame(*child);
350             ASSERT(webFrame);
351
352             builder.append(webFrame->contentsAsString());
353         }
354         // FIXME: It may make sense to use toStringPreserveCapacity() here.
355         return builder.toString();
356     }
357
358     Document* document = m_coreFrame->document();
359     if (!document)
360         return String();
361
362     RefPtr<Element> documentElement = document->documentElement();
363     if (!documentElement)
364         return String();
365
366     RefPtr<Range> range = document->createRange();
367
368     if (range->selectNode(*documentElement).hasException())
369         return String();
370
371     return plainText(range.get());
372 }
373
374 String WebFrame::selectionAsString() const 
375 {
376     if (!m_coreFrame)
377         return String();
378
379     return m_coreFrame->displayStringModifiedByEncoding(m_coreFrame->editor().selectedText());
380 }
381
382 IntSize WebFrame::size() const
383 {
384     if (!m_coreFrame)
385         return IntSize();
386
387     FrameView* frameView = m_coreFrame->view();
388     if (!frameView)
389         return IntSize();
390
391     return frameView->contentsSize();
392 }
393
394 bool WebFrame::isFrameSet() const
395 {
396     if (!m_coreFrame)
397         return false;
398
399     Document* document = m_coreFrame->document();
400     if (!document)
401         return false;
402     return document->isFrameSet();
403 }
404
405 bool WebFrame::isMainFrame() const
406 {
407     if (!m_coreFrame)
408         return false;
409
410     return m_coreFrame->isMainFrame();
411 }
412
413 String WebFrame::name() const
414 {
415     if (!m_coreFrame)
416         return String();
417
418     return m_coreFrame->tree().uniqueName();
419 }
420
421 URL WebFrame::url() const
422 {
423     if (!m_coreFrame)
424         return { };
425
426     auto* documentLoader = m_coreFrame->loader().documentLoader();
427     if (!documentLoader)
428         return { };
429
430     return documentLoader->url();
431 }
432
433 CertificateInfo WebFrame::certificateInfo() const
434 {
435     if (!m_coreFrame)
436         return { };
437
438     DocumentLoader* documentLoader = m_coreFrame->loader().documentLoader();
439     if (!documentLoader)
440         return { };
441
442     return valueOrCompute(documentLoader->response().certificateInfo(), [] { return CertificateInfo(); });
443 }
444
445 String WebFrame::innerText() const
446 {
447     if (!m_coreFrame)
448         return String();
449
450     if (!m_coreFrame->document()->documentElement())
451         return String();
452
453     return m_coreFrame->document()->documentElement()->innerText();
454 }
455
456 WebFrame* WebFrame::parentFrame() const
457 {
458     if (!m_coreFrame || !m_coreFrame->ownerElement())
459         return nullptr;
460
461     auto* frame = m_coreFrame->ownerElement()->document().frame();
462     if (!frame)
463         return nullptr;
464
465     return WebFrame::fromCoreFrame(*frame);
466 }
467
468 Ref<API::Array> WebFrame::childFrames()
469 {
470     if (!m_coreFrame)
471         return API::Array::create();
472
473     size_t size = m_coreFrame->tree().childCount();
474     if (!size)
475         return API::Array::create();
476
477     Vector<RefPtr<API::Object>> vector;
478     vector.reserveInitialCapacity(size);
479
480     for (Frame* child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
481         WebFrame* webFrame = WebFrame::fromCoreFrame(*child);
482         ASSERT(webFrame);
483         vector.uncheckedAppend(webFrame);
484     }
485
486     return API::Array::create(WTFMove(vector));
487 }
488
489 String WebFrame::layerTreeAsText() const
490 {
491     if (!m_coreFrame)
492         return "";
493
494     return m_coreFrame->layerTreeAsText(0);
495 }
496
497 unsigned WebFrame::pendingUnloadCount() const
498 {
499     if (!m_coreFrame)
500         return 0;
501
502     return m_coreFrame->document()->domWindow()->pendingUnloadEventListeners();
503 }
504
505 bool WebFrame::allowsFollowingLink(const URL& url) const
506 {
507     if (!m_coreFrame)
508         return true;
509         
510     return m_coreFrame->document()->securityOrigin().canDisplay(url);
511 }
512
513 JSGlobalContextRef WebFrame::jsContext()
514 {
515     if (!m_coreFrame)
516         return nullptr;
517
518     return toGlobalRef(m_coreFrame->script().globalObject(mainThreadNormalWorld())->globalExec());
519 }
520
521 JSGlobalContextRef WebFrame::jsContextForWorld(InjectedBundleScriptWorld* world)
522 {
523     if (!m_coreFrame)
524         return nullptr;
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 | HitTestRequest::AllowChildFrameContent));
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(WritingDirection::Natural);
806     else if (direction == "ltr")
807         m_coreFrame->editor().setBaseWritingDirection(WritingDirection::LeftToRight);
808     else if (direction == "rtl")
809         m_coreFrame->editor().setBaseWritingDirection(WritingDirection::RightToLeft);
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     auto 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     if (!graphicsContext)
852         return nullptr;
853
854     float deviceScaleFactor = coreFrame()->page()->deviceScaleFactor();
855     graphicsContext->scale(deviceScaleFactor);
856     graphicsContext->drawConsumingImageBuffer(WTFMove(snapshot), FloatPoint());
857
858     return sharedSnapshot;
859 }
860     
861 } // namespace WebKit