summaryrefslogtreecommitdiff
path: root/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage/WebFrame.cpp')
-rw-r--r--Source/WebKit2/WebProcess/WebPage/WebFrame.cpp304
1 files changed, 193 insertions, 111 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp b/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp
index 4b9845d86..30203c647 100644
--- a/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp
+++ b/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,14 +28,20 @@
#include "APIArray.h"
#include "DownloadManager.h"
+#include "FrameInfoData.h"
+#include "InjectedBundleFileHandle.h"
#include "InjectedBundleHitTestResult.h"
#include "InjectedBundleNodeHandle.h"
#include "InjectedBundleRangeHandle.h"
#include "InjectedBundleScriptWorld.h"
+#include "NetworkConnectionToWebProcessMessages.h"
+#include "NetworkProcessConnection.h"
#include "PluginView.h"
#include "WKAPICast.h"
#include "WKBundleAPICast.h"
#include "WebChromeClient.h"
+#include "WebCoreArgumentCoders.h"
+#include "WebDocumentLoader.h"
#include "WebPage.h"
#include "WebPageProxyMessages.h"
#include "WebProcess.h"
@@ -44,18 +50,24 @@
#include <JavaScriptCore/JSLock.h>
#include <JavaScriptCore/JSValueRef.h>
#include <WebCore/ArchiveResource.h>
+#include <WebCore/CertificateInfo.h>
#include <WebCore/Chrome.h>
#include <WebCore/DocumentLoader.h>
#include <WebCore/EventHandler.h>
+#include <WebCore/File.h>
#include <WebCore/Frame.h>
+#include <WebCore/FrameSnapshotting.h>
#include <WebCore/FrameView.h>
#include <WebCore/HTMLFormElement.h>
#include <WebCore/HTMLFrameOwnerElement.h>
#include <WebCore/HTMLInputElement.h>
#include <WebCore/HTMLNames.h>
+#include <WebCore/HTMLSelectElement.h>
#include <WebCore/HTMLTextAreaElement.h>
+#include <WebCore/ImageBuffer.h>
#include <WebCore/JSCSSStyleDeclaration.h>
#include <WebCore/JSElement.h>
+#include <WebCore/JSFile.h>
#include <WebCore/JSRange.h>
#include <WebCore/MainFrame.h>
#include <WebCore/NetworkingContext.h>
@@ -63,24 +75,17 @@
#include <WebCore/Page.h>
#include <WebCore/PluginDocument.h>
#include <WebCore/RenderTreeAsText.h>
-#include <WebCore/ResourceBuffer.h>
-#include <WebCore/ResourceLoader.h>
#include <WebCore/ScriptController.h>
#include <WebCore/SecurityOrigin.h>
+#include <WebCore/SubresourceLoader.h>
#include <WebCore/TextIterator.h>
#include <WebCore/TextResourceDecoder.h>
#include <wtf/text/StringBuilder.h>
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
#include <WebCore/LegacyWebArchive.h>
#endif
-#if ENABLE(NETWORK_PROCESS)
-#include "NetworkConnectionToWebProcessMessages.h"
-#include "NetworkProcessConnection.h"
-#include "WebCoreArgumentCoders.h"
-#endif
-
#ifndef NDEBUG
#include <wtf/RefCountedLeakCounter.h>
#endif
@@ -104,54 +109,51 @@ static uint64_t generateListenerID()
return uniqueListenerID++;
}
-PassRefPtr<WebFrame> WebFrame::createWithCoreMainFrame(WebPage* page, WebCore::Frame* coreFrame)
+Ref<WebFrame> WebFrame::createWithCoreMainFrame(WebPage* page, WebCore::Frame* coreFrame)
{
- RefPtr<WebFrame> frame = create(std::unique_ptr<WebFrameLoaderClient>(static_cast<WebFrameLoaderClient*>(&coreFrame->loader().client())));
- page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID()));
+ auto frame = create(std::unique_ptr<WebFrameLoaderClient>(static_cast<WebFrameLoaderClient*>(&coreFrame->loader().client())));
+ page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID()), page->pageID(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
frame->m_coreFrame = coreFrame;
frame->m_coreFrame->tree().setName(String());
frame->m_coreFrame->init();
- return frame.release();
+ return frame;
}
-PassRefPtr<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
+Ref<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
{
- RefPtr<WebFrame> frame = create(std::make_unique<WebFrameLoaderClient>());
- page->send(Messages::WebPageProxy::DidCreateSubframe(frame->frameID()));
+ auto frame = create(std::make_unique<WebFrameLoaderClient>());
+ page->send(Messages::WebPageProxy::DidCreateSubframe(frame->frameID()), page->pageID(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
+
+ auto coreFrame = Frame::create(page->corePage(), ownerElement, frame->m_frameLoaderClient.get());
+ frame->m_coreFrame = coreFrame.ptr();
- RefPtr<Frame> coreFrame = Frame::create(page->corePage(), ownerElement, frame->m_frameLoaderClient.get());
- frame->m_coreFrame = coreFrame.get();
- frame->m_coreFrame->tree().setName(frameName);
+ coreFrame->tree().setName(frameName);
if (ownerElement) {
ASSERT(ownerElement->document().frame());
- ownerElement->document().frame()->tree().appendChild(coreFrame.release());
+ ownerElement->document().frame()->tree().appendChild(coreFrame.get());
}
- frame->m_coreFrame->init();
- return frame.release();
+ coreFrame->init();
+
+ return frame;
}
-PassRefPtr<WebFrame> WebFrame::create(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient)
+Ref<WebFrame> WebFrame::create(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient)
{
- RefPtr<WebFrame> frame = adoptRef(new WebFrame(std::move(frameLoaderClient)));
+ auto frame = adoptRef(*new WebFrame(WTFMove(frameLoaderClient)));
// Add explict ref() that will be balanced in WebFrameLoaderClient::frameLoaderDestroyed().
frame->ref();
- return frame.release();
+ return frame;
}
WebFrame::WebFrame(std::unique_ptr<WebFrameLoaderClient> frameLoaderClient)
- : m_coreFrame(0)
- , m_policyListenerID(0)
- , m_policyFunction(0)
- , m_policyDownloadID(0)
- , m_frameLoaderClient(std::move(frameLoaderClient))
- , m_loadListener(0)
+ : m_frameLoaderClient(WTFMove(frameLoaderClient))
, m_frameID(generateFrameID())
{
m_frameLoaderClient->setWebFrame(this);
- WebProcess::shared().addWebFrame(m_frameID, this);
+ WebProcess::singleton().addWebFrame(m_frameID, this);
#ifndef NDEBUG
webFrameCounter.increment();
@@ -178,9 +180,31 @@ WebPage* WebFrame::page() const
return 0;
}
+WebFrame* WebFrame::fromCoreFrame(Frame& frame)
+{
+ auto* webFrameLoaderClient = toWebFrameLoaderClient(frame.loader().client());
+ if (!webFrameLoaderClient)
+ return nullptr;
+
+ return webFrameLoaderClient->webFrame();
+}
+
+FrameInfoData WebFrame::info() const
+{
+ FrameInfoData info;
+
+ info.isMainFrame = isMainFrame();
+ // FIXME: This should use the full request.
+ info.request = ResourceRequest(URL(URL(), url()));
+ info.securityOrigin = SecurityOriginData::fromFrame(m_coreFrame);
+ info.frameID = m_frameID;
+
+ return info;
+}
+
void WebFrame::invalidate()
{
- WebProcess::shared().removeWebFrame(m_frameID);
+ WebProcess::singleton().removeWebFrame(m_frameID);
m_coreFrame = 0;
}
@@ -200,12 +224,12 @@ void WebFrame::invalidatePolicyListener()
if (!m_policyListenerID)
return;
- m_policyDownloadID = 0;
+ m_policyDownloadID = { };
m_policyListenerID = 0;
m_policyFunction = 0;
}
-void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action, uint64_t downloadID)
+void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action, uint64_t navigationID, DownloadID downloadID)
{
if (!m_coreFrame)
return;
@@ -218,65 +242,54 @@ void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action
ASSERT(m_policyFunction);
- FramePolicyFunction function = std::move(m_policyFunction);
+ FramePolicyFunction function = WTFMove(m_policyFunction);
invalidatePolicyListener();
m_policyDownloadID = downloadID;
+ if (navigationID) {
+ if (WebDocumentLoader* documentLoader = static_cast<WebDocumentLoader*>(m_coreFrame->loader().policyDocumentLoader()))
+ documentLoader->setNavigationID(navigationID);
+ }
+
function(action);
}
-void WebFrame::startDownload(const WebCore::ResourceRequest& request)
+void WebFrame::startDownload(const WebCore::ResourceRequest& request, const String& suggestedName)
{
- ASSERT(m_policyDownloadID);
-
- uint64_t policyDownloadID = m_policyDownloadID;
- m_policyDownloadID = 0;
+ ASSERT(m_policyDownloadID.downloadID());
-#if ENABLE(NETWORK_PROCESS)
- if (WebProcess::shared().usesNetworkProcess()) {
- WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::StartDownload(page()->sessionID(), policyDownloadID, request), 0);
- return;
- }
-#endif
+ auto policyDownloadID = m_policyDownloadID;
+ m_policyDownloadID = { };
- WebProcess::shared().downloadManager().startDownload(policyDownloadID, request);
+ auto& webProcess = WebProcess::singleton();
+ SessionID sessionID = page() ? page()->sessionID() : SessionID::defaultSessionID();
+ webProcess.networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::StartDownload(sessionID, policyDownloadID, request, suggestedName), 0);
}
-void WebFrame::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, const ResourceRequest& request, const ResourceResponse& response)
+void WebFrame::convertMainResourceLoadToDownload(DocumentLoader* documentLoader, SessionID sessionID, const ResourceRequest& request, const ResourceResponse& response)
{
- ASSERT(m_policyDownloadID);
-
- uint64_t policyDownloadID = m_policyDownloadID;
- m_policyDownloadID = 0;
+ ASSERT(m_policyDownloadID.downloadID());
- ResourceLoader* mainResourceLoader = documentLoader->mainResourceLoader();
+ auto policyDownloadID = m_policyDownloadID;
+ m_policyDownloadID = { };
-#if ENABLE(NETWORK_PROCESS)
- if (WebProcess::shared().usesNetworkProcess()) {
- // Use 0 to indicate that there is no main resource loader.
- // This can happen if the main resource is in the WebCore memory cache.
- uint64_t mainResourceLoadIdentifier;
- if (mainResourceLoader)
- mainResourceLoadIdentifier = mainResourceLoader->identifier();
- else
- mainResourceLoadIdentifier = 0;
+ SubresourceLoader* mainResourceLoader = documentLoader->mainResourceLoader();
- WebProcess::shared().networkConnection()->connection()->send(Messages::NetworkConnectionToWebProcess::ConvertMainResourceLoadToDownload(mainResourceLoadIdentifier, policyDownloadID, request, response), 0);
- return;
- }
-#endif
-
- if (!mainResourceLoader) {
- // The main resource has already been loaded. Start a new download instead.
- WebProcess::shared().downloadManager().startDownload(policyDownloadID, request);
- return;
- }
+ auto& webProcess = WebProcess::singleton();
+ // Use 0 to indicate that the resource load can't be converted and a new download must be started.
+ // This can happen if there is no loader because the main resource is in the WebCore memory cache,
+ // or because the conversion was attempted when not calling SubresourceLoader::didReceiveResponse().
+ uint64_t mainResourceLoadIdentifier;
+ if (mainResourceLoader)
+ mainResourceLoadIdentifier = mainResourceLoader->identifier();
+ else
+ mainResourceLoadIdentifier = 0;
- WebProcess::shared().downloadManager().convertHandleToDownload(policyDownloadID, documentLoader->mainResourceLoader()->handle(), request, response);
+ webProcess.networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::ConvertMainResourceLoadToDownload(sessionID, mainResourceLoadIdentifier, policyDownloadID, request, response), 0);
}
-String WebFrame::source() const
+String WebFrame::source() const
{
if (!m_coreFrame)
return String();
@@ -289,7 +302,7 @@ String WebFrame::source() const
DocumentLoader* documentLoader = m_coreFrame->loader().activeDocumentLoader();
if (!documentLoader)
return String();
- RefPtr<ResourceBuffer> mainResourceData = documentLoader->mainResourceData();
+ RefPtr<SharedBuffer> mainResourceData = documentLoader->mainResourceData();
if (!mainResourceData)
return String();
return decoder->encoding().decode(mainResourceData->data(), mainResourceData->size());
@@ -306,8 +319,7 @@ String WebFrame::contentsAsString() const
if (!builder.isEmpty())
builder.append(' ');
- WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(child->loader().client());
- WebFrame* webFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0;
+ WebFrame* webFrame = WebFrame::fromCoreFrame(*child);
ASSERT(webFrame);
builder.append(webFrame->contentsAsString());
@@ -326,9 +338,7 @@ String WebFrame::contentsAsString() const
RefPtr<Range> range = document->createRange();
- ExceptionCode ec = 0;
- range->selectNode(documentElement.get(), ec);
- if (ec)
+ if (range->selectNode(*documentElement).hasException())
return String();
return plainText(range.get());
@@ -393,6 +403,18 @@ String WebFrame::url() const
return documentLoader->url().string();
}
+CertificateInfo WebFrame::certificateInfo() const
+{
+ if (!m_coreFrame)
+ return { };
+
+ DocumentLoader* documentLoader = m_coreFrame->loader().documentLoader();
+ if (!documentLoader)
+ return { };
+
+ return valueOrCompute(documentLoader->response().certificateInfo(), [] { return CertificateInfo(); });
+}
+
String WebFrame::innerText() const
{
if (!m_coreFrame)
@@ -409,11 +431,10 @@ WebFrame* WebFrame::parentFrame() const
if (!m_coreFrame || !m_coreFrame->ownerElement())
return 0;
- WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(m_coreFrame->ownerElement()->document().frame()->loader().client());
- return webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0;
+ return WebFrame::fromCoreFrame(*m_coreFrame->ownerElement()->document().frame());
}
-PassRefPtr<API::Array> WebFrame::childFrames()
+Ref<API::Array> WebFrame::childFrames()
{
if (!m_coreFrame)
return API::Array::create();
@@ -426,13 +447,12 @@ PassRefPtr<API::Array> WebFrame::childFrames()
vector.reserveInitialCapacity(size);
for (Frame* child = m_coreFrame->tree().firstChild(); child; child = child->tree().nextSibling()) {
- WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(child->loader().client());
- WebFrame* webFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0;
+ WebFrame* webFrame = WebFrame::fromCoreFrame(*child);
ASSERT(webFrame);
vector.uncheckedAppend(webFrame);
}
- return API::Array::create(std::move(vector));
+ return API::Array::create(WTFMove(vector));
}
String WebFrame::layerTreeAsText() const
@@ -456,7 +476,7 @@ bool WebFrame::allowsFollowingLink(const WebCore::URL& url) const
if (!m_coreFrame)
return true;
- return m_coreFrame->document()->securityOrigin()->canDisplay(url);
+ return m_coreFrame->document()->securityOrigin().canDisplay(url);
}
JSGlobalContextRef WebFrame::jsContext()
@@ -479,6 +499,35 @@ bool WebFrame::handlesPageScaleGesture() const
return pluginView && pluginView->handlesPageScaleFactor();
}
+bool WebFrame::requiresUnifiedScaleFactor() const
+{
+ if (!m_coreFrame->document()->isPluginDocument())
+ return 0;
+
+ PluginDocument* pluginDocument = static_cast<PluginDocument*>(m_coreFrame->document());
+ PluginView* pluginView = static_cast<PluginView*>(pluginDocument->pluginWidget());
+ return pluginView && pluginView->requiresUnifiedScaleFactor();
+}
+
+void WebFrame::setAccessibleName(const String& accessibleName)
+{
+ if (!AXObjectCache::accessibilityEnabled())
+ return;
+
+ if (!m_coreFrame)
+ return;
+
+ auto* document = m_coreFrame->document();
+ if (!document)
+ return;
+
+ auto* rootObject = document->axObjectCache()->rootObject();
+ if (!rootObject)
+ return;
+
+ rootObject->setAccessibleName(accessibleName);
+}
+
IntRect WebFrame::contentBounds() const
{
if (!m_coreFrame)
@@ -526,7 +575,7 @@ IntSize WebFrame::scrollOffset() const
if (!view)
return IntSize();
- return view->scrollOffset();
+ return toIntSize(view->scrollPosition());
}
bool WebFrame::hasHorizontalScrollbar() const
@@ -558,7 +607,7 @@ PassRefPtr<InjectedBundleHitTestResult> WebFrame::hitTest(const IntPoint point)
if (!m_coreFrame)
return 0;
- return InjectedBundleHitTestResult::create(m_coreFrame->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent));
+ return InjectedBundleHitTestResult::create(m_coreFrame->eventHandler().hitTestResultAtPoint(point, HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent));
}
bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha)
@@ -587,10 +636,10 @@ bool WebFrame::containsAnyFormElements() const
if (!document)
return false;
- for (Node* node = document->documentElement(); node; node = NodeTraversal::next(node)) {
- if (!node->isElementNode())
+ for (Node* node = document->documentElement(); node; node = NodeTraversal::next(*node)) {
+ if (!is<Element>(*node))
continue;
- if (isHTMLFormElement(node))
+ if (is<HTMLFormElement>(*node))
return true;
}
return false;
@@ -605,10 +654,10 @@ bool WebFrame::containsAnyFormControls() const
if (!document)
return false;
- for (Node* node = document->documentElement(); node; node = NodeTraversal::next(node)) {
- if (!node->isElementNode())
+ for (Node* node = document->documentElement(); node; node = NodeTraversal::next(*node)) {
+ if (!is<Element>(*node))
continue;
- if (isHTMLInputElement(node) || isHTMLSelectElement(node) || isHTMLTextAreaElement(node))
+ if (is<HTMLInputElement>(*node) || is<HTMLSelectElement>(*node) || is<HTMLTextAreaElement>(*node))
return true;
}
return false;
@@ -624,15 +673,12 @@ void WebFrame::stopLoading()
WebFrame* WebFrame::frameForContext(JSContextRef context)
{
- JSObjectRef globalObjectRef = JSContextGetGlobalObject(context);
- JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
- if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0)
- return 0;
- Frame* coreFrame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->impl().frame();
-
- WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(coreFrame->loader().client());
- return webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0;
+ JSC::JSGlobalObject* globalObjectObj = toJS(context)->lexicalGlobalObject();
+ JSDOMWindow* window = jsDynamicDowncast<JSDOMWindow*>(globalObjectObj->vm(), globalObjectObj);
+ if (!window)
+ return nullptr;
+ return WebFrame::fromCoreFrame(*(window->wrapped().frame()));
}
JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world)
@@ -659,12 +705,24 @@ JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleRangeHandle* rangeHandle, I
return toRef(exec, toJS(exec, globalObject, rangeHandle->coreRange()));
}
+JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleFileHandle* fileHandle, InjectedBundleScriptWorld* world)
+{
+ if (!m_coreFrame)
+ return nullptr;
+
+ JSDOMWindow* globalObject = m_coreFrame->script().globalObject(world->coreWorld());
+ ExecState* exec = globalObject->globalExec();
+
+ JSLockHolder lock(exec);
+ return toRef(exec, toJS(exec, globalObject, fileHandle->coreFile()));
+}
+
String WebFrame::counterValue(JSObjectRef element)
{
- if (!toJS(element)->inherits(JSElement::info()))
+ if (!toJS(element)->inherits(*toJS(element)->vm(), JSElement::info()))
return String();
- return counterValueForElement(&jsCast<JSElement*>(toJS(element))->impl());
+ return counterValueForElement(&jsCast<JSElement*>(toJS(element))->wrapped());
}
String WebFrame::provisionalURL() const
@@ -734,15 +792,19 @@ void WebFrame::setTextDirection(const String& direction)
m_coreFrame->editor().setBaseWritingDirection(RightToLeftWritingDirection);
}
-#if PLATFORM(MAC)
+void WebFrame::documentLoaderDetached(uint64_t navigationID)
+{
+ page()->send(Messages::WebPageProxy::DidDestroyNavigation(navigationID));
+}
+
+#if PLATFORM(COCOA)
RetainPtr<CFDataRef> WebFrame::webArchiveData(FrameFilterFunction callback, void* context)
{
- RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(coreFrame()->document(), [this, callback, context](Frame& frame) -> bool {
+ RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(*coreFrame()->document(), [this, callback, context](Frame& frame) -> bool {
if (!callback)
return true;
- WebFrameLoaderClient* webFrameLoaderClient = toWebFrameLoaderClient(frame.loader().client());
- WebFrame* webFrame = webFrameLoaderClient ? webFrameLoaderClient->webFrame() : 0;
+ WebFrame* webFrame = WebFrame::fromCoreFrame(frame);
ASSERT(webFrame);
return callback(toAPI(this), toAPI(webFrame), context);
@@ -754,5 +816,25 @@ RetainPtr<CFDataRef> WebFrame::webArchiveData(FrameFilterFunction callback, void
return archive->rawDataRepresentation();
}
#endif
+
+PassRefPtr<ShareableBitmap> WebFrame::createSelectionSnapshot() const
+{
+ std::unique_ptr<ImageBuffer> snapshot = snapshotSelection(*coreFrame(), WebCore::SnapshotOptionsForceBlackText);
+ if (!snapshot)
+ return nullptr;
+
+ auto sharedSnapshot = ShareableBitmap::createShareable(snapshot->internalSize(), ShareableBitmap::SupportsAlpha);
+ if (!sharedSnapshot)
+ return nullptr;
+
+ // FIXME: We should consider providing a way to use subpixel antialiasing for the snapshot
+ // if we're compositing this image onto a solid color (e.g. the modern find indicator style).
+ auto graphicsContext = sharedSnapshot->createGraphicsContext();
+ float deviceScaleFactor = coreFrame()->page()->deviceScaleFactor();
+ graphicsContext->scale(deviceScaleFactor);
+ graphicsContext->drawConsumingImageBuffer(WTFMove(snapshot), FloatPoint());
+
+ return WTFMove(sharedSnapshot);
+}
} // namespace WebKit