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