Diff
Modified: trunk/Source/WebDriver/ChangeLog (221254 => 221255)
--- trunk/Source/WebDriver/ChangeLog 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebDriver/ChangeLog 2017-08-28 13:55:10 UTC (rev 221255)
@@ -1,5 +1,30 @@
2017-08-28 Carlos Garcia Campos <[email protected]>
+ WebDriver: implement screen capture commands
+ https://bugs.webkit.org/show_bug.cgi?id=174615
+
+ Reviewed by Brian Burg.
+
+ Implement takeScreenshot and takeElementScreenshot commands.
+
+ 19. Screen Capture.
+ https://w3c.github.io/webdriver/webdriver-spec.html#screen-capture
+
+ * CommandResult.cpp:
+ (WebDriver::CommandResult::CommandResult): Handle ScreenshotError protocol error.
+ (WebDriver::CommandResult::httpStatusCode const): Add UnableToCaptureScreen.
+ (WebDriver::CommandResult::errorString const): Ditto.
+ * CommandResult.h:
+ * Session.cpp:
+ (WebDriver::Session::takeScreenshot):
+ * Session.h:
+ * WebDriverService.cpp:
+ (WebDriver::WebDriverService::takeScreenshot):
+ (WebDriver::WebDriverService::takeElementScreenshot):
+ * WebDriverService.h:
+
+2017-08-28 Carlos Garcia Campos <[email protected]>
+
WebDriver: implement cookies commands
https://bugs.webkit.org/show_bug.cgi?id=174613
Modified: trunk/Source/WebDriver/CommandResult.cpp (221254 => 221255)
--- trunk/Source/WebDriver/CommandResult.cpp 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebDriver/CommandResult.cpp 2017-08-28 13:55:10 UTC (rev 221255)
@@ -108,6 +108,8 @@
m_errorCode = ErrorCode::NoSuchAlert;
else if (errorName == "ElementNotSelectable")
m_errorCode = ErrorCode::ElementNotSelectable;
+ else if (errorName == "ScreenshotError")
+ m_errorCode = ErrorCode::UnableToCaptureScreen;
break;
}
@@ -149,6 +151,7 @@
return 408;
case ErrorCode::_javascript_Error:
case ErrorCode::SessionNotCreated:
+ case ErrorCode::UnableToCaptureScreen:
case ErrorCode::UnexpectedAlertOpen:
case ErrorCode::UnknownError:
case ErrorCode::UnsupportedOperation:
@@ -198,6 +201,8 @@
return ASCIILiteral("stale element reference");
case ErrorCode::Timeout:
return ASCIILiteral("timeout");
+ case ErrorCode::UnableToCaptureScreen:
+ return ASCIILiteral("unable to capture screen");
case ErrorCode::UnexpectedAlertOpen:
return ASCIILiteral("unexpected alert open");
case ErrorCode::UnknownCommand:
Modified: trunk/Source/WebDriver/CommandResult.h (221254 => 221255)
--- trunk/Source/WebDriver/CommandResult.h 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebDriver/CommandResult.h 2017-08-28 13:55:10 UTC (rev 221255)
@@ -57,6 +57,7 @@
SessionNotCreated,
StaleElementReference,
Timeout,
+ UnableToCaptureScreen,
UnexpectedAlertOpen,
UnknownCommand,
UnknownError,
Modified: trunk/Source/WebDriver/Session.cpp (221254 => 221255)
--- trunk/Source/WebDriver/Session.cpp 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebDriver/Session.cpp 2017-08-28 13:55:10 UTC (rev 221255)
@@ -1997,4 +1997,39 @@
});
}
+void Session::takeScreenshot(std::optional<String> elementID, std::optional<bool> scrollIntoView, Function<void (CommandResult&&)>&& completionHandler)
+{
+ if (!m_toplevelBrowsingContext) {
+ completionHandler(CommandResult::fail(CommandResult::ErrorCode::NoSuchWindow));
+ return;
+ }
+
+ handleUserPrompts([this, elementID, scrollIntoView, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+ if (result.isError()) {
+ completionHandler(WTFMove(result));
+ return;
+ }
+ RefPtr<InspectorObject> parameters = InspectorObject::create();
+ parameters->setString(ASCIILiteral("handle"), m_toplevelBrowsingContext.value());
+ if (m_currentBrowsingContext)
+ parameters->setString(ASCIILiteral("frameHandle"), m_currentBrowsingContext.value());
+ if (elementID)
+ parameters->setString(ASCIILiteral("nodeHandle"), elementID.value());
+ if (scrollIntoView.value_or(false))
+ parameters->setBoolean(ASCIILiteral("scrollIntoViewIfNeeded"), true);
+ m_host->sendCommandToBackend(ASCIILiteral("takeScreenshot"), WTFMove(parameters), [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)](SessionHost::CommandResponse&& response) mutable {
+ if (response.isError || !response.responseObject) {
+ completionHandler(CommandResult::fail(WTFMove(response.responseObject)));
+ return;
+ }
+ String data;
+ if (!response.responseObject->getString(ASCIILiteral("data"), data)) {
+ completionHandler(CommandResult::fail(CommandResult::ErrorCode::UnknownError));
+ return;
+ }
+ completionHandler(CommandResult::success(InspectorValue::create(data)));
+ });
+ });
+}
+
} // namespace WebDriver
Modified: trunk/Source/WebDriver/Session.h (221254 => 221255)
--- trunk/Source/WebDriver/Session.h 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebDriver/Session.h 2017-08-28 13:55:10 UTC (rev 221255)
@@ -113,6 +113,7 @@
void acceptAlert(Function<void (CommandResult&&)>&&);
void getAlertText(Function<void (CommandResult&&)>&&);
void sendAlertText(const String&, Function<void (CommandResult&&)>&&);
+ void takeScreenshot(std::optional<String> elementID, std::optional<bool> scrollIntoView, Function<void (CommandResult&&)>&&);
private:
Session(std::unique_ptr<SessionHost>&&);
Modified: trunk/Source/WebDriver/WebDriverService.cpp (221254 => 221255)
--- trunk/Source/WebDriver/WebDriverService.cpp 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebDriver/WebDriverService.cpp 2017-08-28 13:55:10 UTC (rev 221255)
@@ -158,6 +158,10 @@
{ HTTPMethod::Get, "/session/$sessionId/alert/text", &WebDriverService::getAlertText },
{ HTTPMethod::Post, "/session/$sessionId/alert/text", &WebDriverService::sendAlertText },
+ { HTTPMethod::Get, "/session/$sessionId/screenshot", &WebDriverService::takeScreenshot },
+ { HTTPMethod::Get, "/session/$sessionId/element/$elementId/screenshot", &WebDriverService::takeElementScreenshot },
+
+
{ HTTPMethod::Get, "/session/$sessionId/element/$elementId/displayed", &WebDriverService::isElementDisplayed },
};
@@ -1507,4 +1511,45 @@
});
}
+void WebDriverService::takeScreenshot(RefPtr<InspectorObject>&& parameters, Function<void (CommandResult&&)>&& completionHandler)
+{
+ // §19.1 Take Screenshot.
+ // https://w3c.github.io/webdriver/webdriver-spec.html#take-screenshot
+ auto session = findSessionOrCompleteWithError(*parameters, completionHandler);
+ if (!session)
+ return;
+
+ session->waitForNavigationToComplete([session, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+ if (result.isError()) {
+ completionHandler(WTFMove(result));
+ return;
+ }
+ session->takeScreenshot(std::nullopt, std::nullopt, WTFMove(completionHandler));
+ });
+}
+
+void WebDriverService::takeElementScreenshot(RefPtr<InspectorObject>&& parameters, Function<void (CommandResult&&)>&& completionHandler)
+{
+ // §19.2 Take Element Screenshot.
+ // https://w3c.github.io/webdriver/webdriver-spec.html#take-element-screenshot
+ auto session = findSessionOrCompleteWithError(*parameters, completionHandler);
+ if (!session)
+ return;
+
+ auto elementID = findElementOrCompleteWithError(*parameters, completionHandler);
+ if (!elementID)
+ return;
+
+ bool scrollIntoView = true;
+ parameters->getBoolean(ASCIILiteral("scroll"), scrollIntoView);
+
+ session->waitForNavigationToComplete([session, elementID, scrollIntoView, completionHandler = WTFMove(completionHandler)](CommandResult&& result) mutable {
+ if (result.isError()) {
+ completionHandler(WTFMove(result));
+ return;
+ }
+ session->takeScreenshot(elementID.value(), scrollIntoView, WTFMove(completionHandler));
+ });
+}
+
} // namespace WebDriver
Modified: trunk/Source/WebDriver/WebDriverService.h (221254 => 221255)
--- trunk/Source/WebDriver/WebDriverService.h 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebDriver/WebDriverService.h 2017-08-28 13:55:10 UTC (rev 221255)
@@ -109,6 +109,8 @@
void acceptAlert(RefPtr<Inspector::InspectorObject>&&, Function<void (CommandResult&&)>&&);
void getAlertText(RefPtr<Inspector::InspectorObject>&&, Function<void (CommandResult&&)>&&);
void sendAlertText(RefPtr<Inspector::InspectorObject>&&, Function<void (CommandResult&&)>&&);
+ void takeScreenshot(RefPtr<Inspector::InspectorObject>&&, Function<void (CommandResult&&)>&&);
+ void takeElementScreenshot(RefPtr<Inspector::InspectorObject>&&, Function<void (CommandResult&&)>&&);
static Capabilities platformCapabilities();
RefPtr<Inspector::InspectorObject> processCapabilities(const Inspector::InspectorObject&, Function<void (CommandResult&&)>&) const;
Modified: trunk/Source/WebKit/ChangeLog (221254 => 221255)
--- trunk/Source/WebKit/ChangeLog 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/ChangeLog 2017-08-28 13:55:10 UTC (rev 221255)
@@ -1,5 +1,32 @@
2017-08-28 Carlos Garcia Campos <[email protected]>
+ WebDriver: implement screen capture commands
+ https://bugs.webkit.org/show_bug.cgi?id=174615
+
+ Reviewed by Brian Burg.
+
+ Extend takeScreenshot command to optionally take a screenshot of an element. When no element is provided, the
+ screenshot is taken from the page visible area.
+
+ * PlatformGTK.cmake: Add WebAutomationSessionCairo.cpp to compilation.
+ * PlatformWPE.cmake: Ditto.
+ * UIProcess/Automation/Automation.json: Add ScreenshotError and several optional parameters to takeScreenshot.
+ * UIProcess/Automation/WebAutomationSession.cpp:
+ (WebKit::WebAutomationSession::takeScreenshot): Receive optional frame, node and scrollIntoView that are
+ checked and passed to the web process.
+ * UIProcess/Automation/WebAutomationSession.h:
+ * UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp: Added.
+ (WebKit::WebAutomationSession::platformGetBase64EncodedPNGData): Cairo implementation.
+ * UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp:
+ * WebProcess/Automation/WebAutomationSessionProxy.cpp:
+ (WebKit::snapshotRectForScreenshot): Helper to get the rectangle to be used for a screenshot.
+ (WebKit::WebAutomationSessionProxy::takeScreenshot): If a node handle is provided take the snapshot using the
+ element rectangle, otherwise use the page visible content rectangle.
+ * WebProcess/Automation/WebAutomationSessionProxy.h:
+ * WebProcess/Automation/WebAutomationSessionProxy.messages.in: Update TakeSnapshot message.
+
+2017-08-28 Carlos Garcia Campos <[email protected]>
+
Automation: takeScreenshot should use the visible content rect not the document rect
https://bugs.webkit.org/show_bug.cgi?id=175665
Modified: trunk/Source/WebKit/PlatformGTK.cmake (221254 => 221255)
--- trunk/Source/WebKit/PlatformGTK.cmake 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/PlatformGTK.cmake 2017-08-28 13:55:10 UTC (rev 221255)
@@ -191,6 +191,8 @@
UIProcess/API/gtk/WebKitWebViewBaseAccessible.cpp
UIProcess/API/gtk/WebKitWebViewGtk.cpp
+ UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp
+
UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp
UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp
Modified: trunk/Source/WebKit/PlatformWPE.cmake (221254 => 221255)
--- trunk/Source/WebKit/PlatformWPE.cmake 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/PlatformWPE.cmake 2017-08-28 13:55:10 UTC (rev 221255)
@@ -197,6 +197,8 @@
UIProcess/API/wpe/WebKitWebViewWPE.cpp
UIProcess/API/wpe/WPEView.cpp
+ UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp
+
UIProcess/Launcher/wpe/ProcessLauncherWPE.cpp
UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp
Modified: trunk/Source/WebKit/UIProcess/Automation/Automation.json (221254 => 221255)
--- trunk/Source/WebKit/UIProcess/Automation/Automation.json 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/UIProcess/Automation/Automation.json 2017-08-28 13:55:10 UTC (rev 221255)
@@ -60,7 +60,8 @@
"InvalidParameter",
"InvalidSelector",
"ElementNotInteractable",
- "ElementNotSelectable"
+ "ElementNotSelectable",
+ "ScreenshotError"
]
},
{
@@ -377,9 +378,12 @@
},
{
"name": "takeScreenshot",
- "description": "Take a screenshot of the current page in a browsing context.",
+ "description": "Take a screenshot of the current page or given element in a browsing context.",
"parameters": [
- { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context to take a screenshot of." }
+ { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context to take a screenshot of." },
+ { "name": "frameHandle", "$ref": "FrameHandle", "optional": true, "description": "The handle for the frame that contains the element. The main frame is used if this parameter is empty string or excluded." },
+ { "name": "nodeHandle", "$ref": "NodeHandle", "optional": true, "description": "The handle of the element to take a screenshot of. The browsing context document element is used if this parameter is excluded." },
+ { "name": "scrollIntoViewIfNeeded", "type": "boolean", "optional": true, "description": "If the element should be scrolled into view before taking the screenshot." }
],
"returns": [
{ "name": "data", "type": "string", "description": "Base64-encoded image data (PNG)." }
Modified: trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp (221254 => 221255)
--- trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp 2017-08-28 13:55:10 UTC (rev 221255)
@@ -1351,16 +1351,23 @@
#endif // PLATFORM(COCOA)
}
-void WebAutomationSession::takeScreenshot(ErrorString& errorString, const String& handle, Ref<TakeScreenshotCallback>&& callback)
+void WebAutomationSession::takeScreenshot(ErrorString& errorString, const String& handle, const String* optionalFrameHandle, const String* optionalNodeHandle, const bool* optionalScrollIntoViewIfNeeded, Ref<TakeScreenshotCallback>&& callback)
{
WebPageProxy* page = webPageProxyForHandle(handle);
if (!page)
FAIL_WITH_PREDEFINED_ERROR(WindowNotFound);
+ std::optional<uint64_t> frameID = webFrameIDForHandle(optionalFrameHandle ? *optionalFrameHandle : emptyString());
+ if (!frameID)
+ FAIL_WITH_PREDEFINED_ERROR(FrameNotFound);
+
+ bool scrollIntoViewIfNeeded = optionalScrollIntoViewIfNeeded ? *optionalScrollIntoViewIfNeeded : false;
+ String nodeHandle = optionalNodeHandle ? *optionalNodeHandle : emptyString();
+
uint64_t callbackID = m_nextScreenshotCallbackID++;
m_screenshotCallbacks.set(callbackID, WTFMove(callback));
- page->process().send(Messages::WebAutomationSessionProxy::TakeScreenshot(page->pageID(), callbackID), 0);
+ page->process().send(Messages::WebAutomationSessionProxy::TakeScreenshot(page->pageID(), frameID.value(), nodeHandle, scrollIntoViewIfNeeded, callbackID), 0);
}
void WebAutomationSession::didTakeScreenshot(uint64_t callbackID, const ShareableBitmap::Handle& imageDataHandle, const String& errorType)
@@ -1389,7 +1396,7 @@
void WebAutomationSession::platformSimulateMouseInteraction(WebKit::WebPageProxy&, const WebCore::IntPoint&, Inspector::Protocol::Automation::MouseInteraction, Inspector::Protocol::Automation::MouseButton, WebEvent::Modifiers)
{
}
-#endif // !PLATFORM(MAC)
+#endif // !PLATFORM(MAC) && !PLATFORM(GTK)
#if !PLATFORM(COCOA) && !PLATFORM(GTK)
void WebAutomationSession::platformSimulateKeyStroke(WebPageProxy&, Inspector::Protocol::Automation::KeyboardInteractionType, Inspector::Protocol::Automation::VirtualKey)
@@ -1399,11 +1406,13 @@
void WebAutomationSession::platformSimulateKeySequence(WebPageProxy&, const String&)
{
}
+#endif // !PLATFORM(COCOA) && !PLATFORM(GTK)
+#if !PLATFORM(COCOA) && !USE(CAIRO)
std::optional<String> WebAutomationSession::platformGetBase64EncodedPNGData(const ShareableBitmap::Handle&)
{
- return String();
+ return std::nullopt;
}
-#endif // !PLATFORM(COCOA)
+#endif // !PLATFORM(COCOA) && !USE(CAIRO)
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.h (221254 => 221255)
--- trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.h 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/UIProcess/Automation/WebAutomationSession.h 2017-08-28 13:55:10 UTC (rev 221255)
@@ -130,7 +130,7 @@
void evaluateJavaScriptFunction(Inspector::ErrorString&, const String& browsingContextHandle, const String* optionalFrameHandle, const String& function, const Inspector::InspectorArray& arguments, const bool* optionalExpectsImplicitCallbackArgument, const int* optionalCallbackTimeout, Ref<Inspector::AutomationBackendDispatcherHandler::EvaluateJavaScriptFunctionCallback>&&) override;
void performMouseInteraction(Inspector::ErrorString&, const String& handle, const Inspector::InspectorObject& requestedPosition, const String& mouseButton, const String& mouseInteraction, const Inspector::InspectorArray& keyModifiers, RefPtr<Inspector::Protocol::Automation::Point>& updatedPosition) override;
void performKeyboardInteractions(Inspector::ErrorString&, const String& handle, const Inspector::InspectorArray& interactions, Ref<PerformKeyboardInteractionsCallback>&&) override;
- void takeScreenshot(Inspector::ErrorString&, const String& handle, Ref<Inspector::AutomationBackendDispatcherHandler::TakeScreenshotCallback>&&) override;
+ void takeScreenshot(Inspector::ErrorString&, const String& handle, const String* optionalFrameHandle, const String* optionalNodeHandle, const bool* optionalScrollIntoViewIfNeeded, Ref<TakeScreenshotCallback>&&) override;
void resolveChildFrameHandle(Inspector::ErrorString&, const String& browsingContextHandle, const String* optionalFrameHandle, const int* optionalOrdinal, const String* optionalName, const String* optionalNodeHandle, Ref<ResolveChildFrameHandleCallback>&&) override;
void resolveParentFrameHandle(Inspector::ErrorString&, const String& browsingContextHandle, const String& frameHandle, Ref<ResolveParentFrameHandleCallback>&&) override;
void computeElementLayout(Inspector::ErrorString&, const String& browsingContextHandle, const String& frameHandle, const String& nodeHandle, const bool* optionalScrollIntoViewIfNeeded, const bool* useViewportCoordinates, Ref<Inspector::AutomationBackendDispatcherHandler::ComputeElementLayoutCallback>&&) override;
Added: trunk/Source/WebKit/UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp (0 => 221255)
--- trunk/Source/WebKit/UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp (rev 0)
+++ trunk/Source/WebKit/UIProcess/Automation/cairo/WebAutomationSessionCairo.cpp 2017-08-28 13:55:10 UTC (rev 221255)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebAutomationSession.h"
+
+#include <WebCore/RefPtrCairo.h>
+#include <cairo/cairo.h>
+#include <wtf/text/Base64.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+std::optional<String> WebAutomationSession::platformGetBase64EncodedPNGData(const ShareableBitmap::Handle& handle)
+{
+ RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(handle, SharedMemory::Protection::ReadOnly);
+ if (!bitmap)
+ return std::nullopt;
+
+ auto surface = bitmap->createCairoSurface();
+ if (!surface)
+ return std::nullopt;
+
+ Vector<unsigned char> pngData;
+ cairo_surface_write_to_png_stream(surface.get(), [](void* userData, const unsigned char* data, unsigned length) -> cairo_status_t {
+ auto* pngData = static_cast<Vector<unsigned char>*>(userData);
+ pngData->append(data, length);
+ return CAIRO_STATUS_SUCCESS;
+ }, &pngData);
+
+ if (pngData.isEmpty())
+ return std::nullopt;
+
+ return base64Encode(pngData);
+}
+
+} // namespace WebKit
+
Modified: trunk/Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp (221254 => 221255)
--- trunk/Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/UIProcess/Automation/gtk/WebAutomationSessionGtk.cpp 2017-08-28 13:55:10 UTC (rev 221255)
@@ -309,11 +309,5 @@
} while (*p);
}
-std::optional<String> WebAutomationSession::platformGetBase64EncodedPNGData(const ShareableBitmap::Handle&)
-{
- // FIXME: Implement this, possibly moving it to a WebAutomationSessionCairo.cpp file.
- return std::nullopt;
-}
-
} // namespace WebKit
Modified: trunk/Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.cpp (221254 => 221255)
--- trunk/Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.cpp 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.cpp 2017-08-28 13:55:10 UTC (rev 221255)
@@ -53,6 +53,7 @@
#include <WebCore/HTMLSelectElement.h>
#include <WebCore/JSElement.h>
#include <WebCore/MainFrame.h>
+#include <WebCore/RenderElement.h>
#include <wtf/UUID.h>
namespace WebKit {
@@ -633,8 +634,24 @@
WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidSelectOptionElement(callbackID, { }), 0);
}
-void WebAutomationSessionProxy::takeScreenshot(uint64_t pageID, uint64_t callbackID)
+static WebCore::IntRect snapshotRectForScreenshot(WebPage& page, WebCore::Element* element)
{
+ if (element) {
+ if (!element->renderer())
+ return { };
+
+ WebCore::LayoutRect topLevelRect;
+ return WebCore::snappedIntRect(element->renderer()->paintingRootRect(topLevelRect));
+ }
+
+ if (auto* frameView = page.mainFrameView())
+ return frameView->visibleContentRect();
+
+ return { };
+}
+
+void WebAutomationSessionProxy::takeScreenshot(uint64_t pageID, uint64_t frameID, String nodeHandle, bool scrollIntoViewIfNeeded, uint64_t callbackID)
+{
ShareableBitmap::Handle handle;
WebPage* page = WebProcess::singleton().webPage(pageID);
@@ -644,23 +661,41 @@
return;
}
- WebCore::FrameView* frameView = page->mainFrameView();
- if (!frameView) {
- WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, String()), 0);
+ WebFrame* frame = frameID ? WebProcess::singleton().webFrame(frameID) : page->mainWebFrame();
+ if (!frame || !frame->coreFrame()) {
+ String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
+ WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, frameNotFoundErrorType), 0);
return;
}
- WebCore::IntRect snapshotRect = frameView->visibleContentRect();
+ WebCore::Element* coreElement = nullptr;
+ if (!nodeHandle.isEmpty()) {
+ coreElement = elementForNodeHandle(*frame, nodeHandle);
+ if (!coreElement) {
+ String nodeNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::NodeNotFound);
+ WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, nodeNotFoundErrorType), 0);
+ return;
+ }
+ }
+
+ String screenshotErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::ScreenshotError);
+ WebCore::IntRect snapshotRect = snapshotRectForScreenshot(*page, coreElement);
if (snapshotRect.isEmpty()) {
- WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, String()), 0);
+ WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, screenshotErrorType), 0);
return;
}
+ if (coreElement && scrollIntoViewIfNeeded)
+ coreElement->scrollIntoViewIfNeeded(false);
+
RefPtr<WebImage> image = page->scaledSnapshotWithOptions(snapshotRect, 1, SnapshotOptionsShareable);
- if (image)
- image->bitmap().createHandle(handle, SharedMemory::Protection::ReadOnly);
+ if (!image) {
+ WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, screenshotErrorType), 0);
+ return;
+ }
- WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, String()), 0);
+ image->bitmap().createHandle(handle, SharedMemory::Protection::ReadOnly);
+ WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidTakeScreenshot(callbackID, handle, { }), 0);
}
void WebAutomationSessionProxy::getCookiesForFrame(uint64_t pageID, uint64_t frameID, uint64_t callbackID)
Modified: trunk/Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.h (221254 => 221255)
--- trunk/Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.h 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.h 2017-08-28 13:55:10 UTC (rev 221255)
@@ -66,7 +66,7 @@
void focusFrame(uint64_t pageID, uint64_t frameID);
void computeElementLayout(uint64_t pageID, uint64_t frameID, String nodeHandle, bool scrollIntoViewIfNeeded, bool useViewportCoordinates, uint64_t callbackID);
void selectOptionElement(uint64_t pageID, uint64_t frameID, String nodeHandle, uint64_t callbackID);
- void takeScreenshot(uint64_t pageID, uint64_t callbackID);
+ void takeScreenshot(uint64_t pageID, uint64_t frameID, String nodeHandle, bool scrollIntoViewIfNeeded, uint64_t callbackID);
void getCookiesForFrame(uint64_t pageID, uint64_t frameID, uint64_t callbackID);
void deleteCookie(uint64_t pageID, uint64_t frameID, String cookieName, uint64_t callbackID);
Modified: trunk/Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.messages.in (221254 => 221255)
--- trunk/Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.messages.in 2017-08-28 13:39:11 UTC (rev 221254)
+++ trunk/Source/WebKit/WebProcess/Automation/WebAutomationSessionProxy.messages.in 2017-08-28 13:55:10 UTC (rev 221255)
@@ -34,7 +34,7 @@
SelectOptionElement(uint64_t pageID, uint64_t frameID, String nodeHandle, uint64_t callbackID)
- TakeScreenshot(uint64_t pageID, uint64_t callbackID)
+ TakeScreenshot(uint64_t pageID, uint64_t frameID, String nodeHandle, bool scrollIntoViewIfNeeded, uint64_t callbackID)
GetCookiesForFrame(uint64_t pageID, uint64_t frameID, uint64_t callbackID)
DeleteCookie(uint64_t pageID, uint64_t frameID, String cookieName, uint64_t callbackID)