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