Diff
Modified: trunk/Source/WebKit2/ChangeLog (148525 => 148526)
--- trunk/Source/WebKit2/ChangeLog 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/ChangeLog 2013-04-16 18:29:43 UTC (rev 148526)
@@ -1,3 +1,55 @@
+2013-04-16 Claudio Saavedra <[email protected]>
+
+ [GTK][WK2] Add API to retrieve a snapshot from a webview
+ https://bugs.webkit.org/show_bug.cgi?id=98270
+
+ Reviewed by Anders Carlsson.
+
+ This adds the GTK+ API necessary to retrieve a snapshot from a
+ webview asynchronously. The API uses the injected bundle
+ internally to get the snapshot from the WebProcess.
+
+ * UIProcess/API/gtk/WebKitError.cpp:
+ (webkit_snapshot_error_quark): Add snapshot API related error
+ quark.
+ * UIProcess/API/gtk/WebKitError.h: Add snapshot error handling.
+ * UIProcess/API/gtk/WebKitInjectedBundleClient.cpp:
+ (didReceiveWebViewMessageFromInjectedBundle): Handle the new
+ "DidGetSnapshot" message.
+ * UIProcess/API/gtk/WebKitPrivate.h: Add SnapshotRegion enum.
+ * UIProcess/API/gtk/WebKitWebView.cpp:
+ (_WebKitWebViewPrivate): Add a map for the snapshot results.
+ (GetSnapshotAsyncData):
+ (webKitWebViewDidReceiveSnapshot):
+ (webKitSnapshotRegionToSnapshotRegion): Helper method for casting
+ the region option enumeration.
+ (generateSnapshotCallbackID): Method to generate unique callback
+ ids.
+ (webkit_web_view_get_snapshot):
+ (webkit_web_view_get_snapshot_finish): New snapshotting API.
+ * UIProcess/API/gtk/WebKitWebView.h: Ditto.
+ * UIProcess/API/gtk/WebKitWebViewPrivate.h: Add the private method
+ to handle a received snapshot.
+ * UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Add the new API
+ bits.
+ * UIProcess/API/gtk/tests/TestWebKitWebView.cpp:
+ (cairoSurfacesEqual): Add helper to compare cairo_surface_t
+ structs.
+ (testWebViewSnapshot): New test.
+ (beforeAll): Add the new test.
+ * UIProcess/API/gtk/tests/WebViewTest.cpp:
+ (WebViewTest::selectAll): Add method to help test snapshots
+ including selection.
+ * UIProcess/API/gtk/tests/WebViewTest.h: Ditto
+ * WebProcess/InjectedBundle/API/gtk/WebKitWebExtension.cpp:
+ (didReceiveMessageToPage): Ditto.
+ (webkitWebExtensionCreate): Register method above.
+ * WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp:
+ (webkitWebPageDidReceiveMessage): Add this method. It
+ handles the new message "GetSnapshot".
+ * WebProcess/InjectedBundle/API/gtk/WebKitWebPagePrivate.h:
+ Add method above.
+
2013-04-16 Timothy Hatcher <[email protected]>
Create full rects for the inspector and inspected views when
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitError.cpp 2013-04-16 18:29:43 UTC (rev 148526)
@@ -91,3 +91,8 @@
{
return g_quark_from_static_string("WebKitJavascriptError");
}
+
+GQuark webkit_snapshot_error_quark()
+{
+ return g_quark_from_static_string("WebKitSnapshotError");
+}
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitError.h (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitError.h 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitError.h 2013-04-16 18:29:43 UTC (rev 148526)
@@ -35,6 +35,7 @@
#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark ()
#define WEBKIT_PRINT_ERROR webkit_print_error_quark ()
#define WEBKIT_JAVASCRIPT_ERROR webkit_print_error_quark ()
+#define WEBKIT_SNAPSHOT_ERROR webkit_snapshot_error_quark ()
/**
* WebKitNetworkError:
@@ -130,6 +131,16 @@
WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED = 699
} WebKitJavascriptError;
+/**
+ * WebKitSnapshotError:
+ * @WEBKIT_SNAPSHOT_ERROR_FAILED_TO_CREATE: An error occurred when creating a webpage snapshot.
+ *
+ * Enum values used to denote errors happending when creating snapshots of #WebKitWebView
+ */
+typedef enum {
+ WEBKIT_SNAPSHOT_ERROR_FAILED_TO_CREATE = 799
+} WebKitSnapshotError;
+
WEBKIT_API GQuark
webkit_network_error_quark (void);
@@ -148,6 +159,9 @@
WEBKIT_API GQuark
webkit_javascript_error_quark (void);
+WEBKIT_API GQuark
+webkit_snapshot_error_quark (void);
+
G_END_DECLS
#endif
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitInjectedBundleClient.cpp (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitInjectedBundleClient.cpp 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitInjectedBundleClient.cpp 2013-04-16 18:29:43 UTC (rev 148526)
@@ -20,6 +20,7 @@
#include "config.h"
#include "WebKitInjectedBundleClient.h"
+#include "WebImage.h"
#include "WebKitURIRequestPrivate.h"
#include "WebKitURIResponsePrivate.h"
#include "WebKitWebContextPrivate.h"
@@ -90,6 +91,10 @@
webkitWebResourceFailed(resource.get(), resourceError.get());
webkitWebViewRemoveLoadingWebResource(webView, resourceIdentifier->value());
+ } else if (g_str_equal(messageName, "DidGetSnapshot")) {
+ WebUInt64* callbackID = static_cast<WebUInt64*>(message.get("CallbackID"));
+ WebImage* image = static_cast<WebImage*>(message.get("Snapshot"));
+ webKitWebViewDidReceiveSnapshot(webView, callbackID->value(), image);
} else
ASSERT_NOT_REACHED();
}
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h 2013-04-16 18:29:43 UTC (rev 148526)
@@ -120,4 +120,9 @@
unsigned wkEventModifiersToGdkModifiers(WKEventModifiers);
unsigned wkEventMouseButtonToWebKitMouseButton(WKEventMouseButton);
+enum SnapshotRegion {
+ SnapshotRegionVisible,
+ SnapshotRegionFullDocument
+};
+
#endif // WebKitPrivate_h
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp 2013-04-16 18:29:43 UTC (rev 148526)
@@ -21,6 +21,7 @@
#include "config.h"
#include "WebKitWebView.h"
+#include "ImageOptions.h"
#include "PlatformCertificateInfo.h"
#include "WebCertificateInfo.h"
#include "WebContextMenuItem.h"
@@ -133,6 +134,7 @@
};
typedef HashMap<uint64_t, GRefPtr<WebKitWebResource> > LoadingResourcesMap;
+typedef HashMap<uint64_t, GRefPtr<GSimpleAsyncResult> > SnapshotResultsMap;
struct _WebKitWebViewPrivate {
~_WebKitWebViewPrivate()
@@ -178,6 +180,8 @@
GRefPtr<GCancellable> faviconCancellable;
CString faviconURI;
unsigned long faviconChangedHandlerID;
+
+ SnapshotResultsMap snapshotResultsMap;
};
static guint signals[LAST_SIGNAL] = { 0, };
@@ -2920,3 +2924,106 @@
return !!certificateInfo.certificate();
}
+
+struct GetSnapshotAsyncData {
+ GRefPtr<GCancellable> cancellable;
+ RefPtr<cairo_surface_t> snapshot;
+};
+WEBKIT_DEFINE_ASYNC_DATA_STRUCT(GetSnapshotAsyncData)
+
+void webKitWebViewDidReceiveSnapshot(WebKitWebView* webView, uint64_t callbackID, WebImage* webImage)
+{
+ GRefPtr<GSimpleAsyncResult> result = webView->priv->snapshotResultsMap.take(callbackID);
+ GetSnapshotAsyncData* data = ""
+ GError* error = 0;
+ if (g_cancellable_set_error_if_cancelled(data->cancellable.get(), &error))
+ g_simple_async_result_take_error(result.get(), error);
+ else if (webImage) {
+ if (RefPtr<ShareableBitmap> image = webImage->bitmap())
+ data->snapshot = image->createCairoSurface();
+ } else {
+ g_set_error_literal(&error, WEBKIT_SNAPSHOT_ERROR, WEBKIT_SNAPSHOT_ERROR_FAILED_TO_CREATE, _("There was an error creating the snapshot"));
+ g_simple_async_result_take_error(result.get(), error);
+ }
+
+ g_simple_async_result_complete(result.get());
+}
+
+COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_SNAPSHOT_REGION_VISIBLE, SnapshotRegionVisible);
+COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_SNAPSHOT_REGION_FULL_DOCUMENT, SnapshotRegionFullDocument);
+
+static inline unsigned webKitSnapshotOptionsToSnapshotOptions(WebKitSnapshotOptions options)
+{
+ SnapshotOptions snapshotOptions = 0;
+
+ if (!(options & WEBKIT_SNAPSHOT_OPTIONS_INCLUDE_SELECTION_HIGHLIGHTING))
+ snapshotOptions |= SnapshotOptionsExcludeSelectionHighlighting;
+
+ return snapshotOptions;
+}
+
+static inline uint64_t generateSnapshotCallbackID()
+{
+ static uint64_t uniqueCallbackID = 1;
+ return uniqueCallbackID++;
+}
+
+/**
+ * webkit_web_view_get_snapshot:
+ * @web_view: a #WebKitWebView
+ * @options: #WebKitSnapshotOptions for the snapshot
+ * @region: the #WebKitSnapshotRegion for this snapshot
+ * @cancellable: (allow-none): a #GCancellable
+ * @callback: (scope async): a #GAsyncReadyCallback
+ * @user_data: (closure): user data
+ *
+ * Asynchronously retrieves a snapshot of @web_view for @region.
+ * @options specifies how the snapshot should be rendered.
+ *
+ * When the operation is finished, @callback will be called. You must
+ * call webkit_web_view_get_snapshot_finish() to get the result of the
+ * operation.
+ */
+void webkit_web_view_get_snapshot(WebKitWebView* webView, WebKitSnapshotRegion region, WebKitSnapshotOptions options, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
+{
+ g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
+
+ GRefPtr<GSimpleAsyncResult> result = adoptGRef(g_simple_async_result_new(G_OBJECT(webView), callback, userData,
+ reinterpret_cast<gpointer>(webkit_web_view_get_snapshot)));
+ GetSnapshotAsyncData* data = ""
+ data->cancellable = cancellable;
+ g_simple_async_result_set_op_res_gpointer(result.get(), data, reinterpret_cast<GDestroyNotify>(destroyGetSnapshotAsyncData));
+
+ ImmutableDictionary::MapType message;
+ uint64_t callbackID = generateSnapshotCallbackID();
+ message.set(String::fromUTF8("SnapshotOptions"), WebUInt64::create(static_cast<uint64_t>(webKitSnapshotOptionsToSnapshotOptions(options))));
+ message.set(String::fromUTF8("SnapshotRegion"), WebUInt64::create(static_cast<uint64_t>(region)));
+ message.set(String::fromUTF8("CallbackID"), WebUInt64::create(callbackID));
+
+ webView->priv->snapshotResultsMap.set(callbackID, result.get());
+ getPage(webView)->postMessageToInjectedBundle(String::fromUTF8("GetSnapshot"), ImmutableDictionary::adopt(message).get());
+}
+
+/**
+ * webkit_web_view_get_snapshot_finish:
+ * @web_view: a #WebKitWebView
+ * @result: a #GAsyncResult
+ * @error: return location for error or %NULL to ignore
+ *
+ * Finishes an asynchronous operation started with webkit_web_view_get_snapshot().
+ *
+ * Returns: (transfer full): a #cairo_surface_t with the retrieved snapshot or %NULL in error.
+ */
+cairo_surface_t* webkit_web_view_get_snapshot_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
+{
+ g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
+ g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0);
+
+ GSimpleAsyncResult* simple = G_SIMPLE_ASYNC_RESULT(result);
+ g_warn_if_fail(g_simple_async_result_get_source_tag(simple) == webkit_web_view_get_snapshot);
+
+ if (g_simple_async_result_propagate_error(simple, error))
+ return 0;
+
+ return cairo_surface_reference(static_cast<GetSnapshotAsyncData*>(g_simple_async_result_get_op_res_gpointer(simple))->snapshot.get());
+}
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h 2013-04-16 18:29:43 UTC (rev 148526)
@@ -159,6 +159,34 @@
WEBKIT_VIEW_MODE_SOURCE
} WebKitViewMode;
+/**
+ * WebKitSnapshotOptions:
+ * @WEBKIT_SNAPSHOT_OPTIONS_NONE: Do not include any special options.
+ * @WEBKIT_SNAPSHOT_OPTIONS_INCLUDE_SELECTION_HIGHLIGHTING: Whether to include in the
+ * snapshot the highlight of the selected content.
+ *
+ * Enum values used to specify options when taking a snapshot
+ * from a #WebKitWebView.
+ */
+typedef enum {
+ WEBKIT_SNAPSHOT_OPTIONS_NONE = 0,
+ WEBKIT_SNAPSHOT_OPTIONS_INCLUDE_SELECTION_HIGHLIGHTING = 1 << 0,
+} WebKitSnapshotOptions;
+
+/**
+ * WebKitSnapshotRegion:
+ * @WEBKIT_SNAPSHOT_REGION_VISIBLE: Specifies a snapshot only for the area that is
+ * visible in the webview
+ * @WEBKIT_SNAPSHOT_REGION_FULL_DOCUMENT: A snapshot of the entire document.
+ *
+ * Enum values used to specify the region from which to get a #WebKitWebView
+ * snapshot
+ */
+typedef enum {
+ WEBKIT_SNAPSHOT_REGION_VISIBLE = 0,
+ WEBKIT_SNAPSHOT_REGION_FULL_DOCUMENT,
+} WebKitSnapshotRegion;
+
struct _WebKitWebView {
WebKitWebViewBase parent;
@@ -418,7 +446,18 @@
webkit_web_view_get_tls_info (WebKitWebView *web_view,
GTlsCertificate **certificate,
GTlsCertificateFlags *errors);
+WEBKIT_API void
+webkit_web_view_get_snapshot (WebKitWebView *web_view,
+ WebKitSnapshotRegion region,
+ WebKitSnapshotOptions options,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+WEBKIT_API cairo_surface_t *
+webkit_web_view_get_snapshot_finish (WebKitWebView *web_view,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
#endif
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h 2013-04-16 18:29:43 UTC (rev 148526)
@@ -27,6 +27,7 @@
#ifndef WebKitWebViewPrivate_h
#define WebKitWebViewPrivate_h
+#include "WebImage.h"
#include "WebKitWebView.h"
#include <wtf/text/CString.h>
@@ -50,6 +51,7 @@
void webkitWebViewResourceLoadStarted(WebKitWebView*, WebKit::WebFrameProxy*, uint64_t resourceIdentifier, WebKitURIRequest*);
void webkitWebViewRunFileChooserRequest(WebKitWebView*, WebKitFileChooserRequest*);
WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier);
+void webKitWebViewDidReceiveSnapshot(WebKitWebView*, uint64_t callbackID, WebKit::WebImage*);
void webkitWebViewRemoveLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier);
bool webkitWebViewEnterFullScreen(WebKitWebView*);
bool webkitWebViewLeaveFullScreen(WebKitWebView*);
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt 2013-04-16 18:29:43 UTC (rev 148526)
@@ -75,6 +75,8 @@
WebKitSaveMode
WebKitViewMode
WebKitInsecureContentEvent
+WebKitSnapshotOptions
+WebKitSnapshotRegion
<SUBSECTION Editing Commands>
WEBKIT_EDITING_COMMAND_CUT
@@ -134,6 +136,8 @@
webkit_web_view_set_view_mode
webkit_web_view_get_view_mode
webkit_web_view_get_tls_info
+webkit_web_view_get_snapshot
+webkit_web_view_get_snapshot_finish
<SUBSECTION WebKitJavascriptResult>
WebKitJavascriptResult
@@ -607,18 +611,21 @@
WEBKIT_DOWNLOAD_ERROR
WEBKIT_PRINT_ERROR
WEBKIT_JAVASCRIPT_ERROR
+WEBKIT_SNAPSHOT_ERROR
WebKitNetworkError
WebKitPluginError
WebKitPolicyError
WebKitDownloadError
WebKitPrintError
WebKitJavascriptError
+WebKitSnapshotError
webkit_network_error_quark
webkit_plugin_error_quark
webkit_policy_error_quark
webkit_download_error_quark
webkit_print_error_quark
webkit_javascript_error_quark
+webkit_snapshot_error_quark
</SECTION>
<SECTION>
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp 2013-04-16 18:29:43 UTC (rev 148526)
@@ -1146,6 +1146,135 @@
g_assert(WebViewTest::_javascript_ResultToBoolean(_javascript_Result));
}
+class SnapshotWebViewTest: public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(SnapshotWebViewTest);
+
+ SnapshotWebViewTest()
+ : m_surface(0)
+ {
+ }
+
+ ~SnapshotWebViewTest()
+ {
+ cairo_surface_destroy(m_surface);
+ }
+
+ static void onSnapshotReady(WebKitWebView* web_view, GAsyncResult* res, SnapshotWebViewTest* test)
+ {
+ GOwnPtr<GError> error;
+ test->m_surface = webkit_web_view_get_snapshot_finish(web_view, res, &error.outPtr());
+ g_assert(!test->m_surface || !error.get());
+ if (error)
+ g_assert_error(error.get(), WEBKIT_SNAPSHOT_ERROR, WEBKIT_SNAPSHOT_ERROR_FAILED_TO_CREATE);
+ test->quitMainLoop();
+ }
+
+ cairo_surface_t* waitForSnapshot(WebKitSnapshotRegion region, WebKitSnapshotOptions options)
+ {
+ m_surface = 0;
+ webkit_web_view_get_snapshot(m_webView, region, options, 0, reinterpret_cast<GAsyncReadyCallback>(onSnapshotReady), this);
+ g_main_loop_run(m_mainLoop);
+ return cairo_surface_reference(m_surface);
+ }
+
+ static void onSnapshotCancelledReady(WebKitWebView* web_view, GAsyncResult* res, SnapshotWebViewTest* test)
+ {
+ GOwnPtr<GError> error;
+ test->m_surface = webkit_web_view_get_snapshot_finish(web_view, res, &error.outPtr());
+ g_assert(!test->m_surface);
+ g_assert_error(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ test->quitMainLoop();
+ }
+
+ gboolean getSnapshotAndCancel()
+ {
+ m_surface = 0;
+ GRefPtr<GCancellable> cancellable = adoptGRef(g_cancellable_new());
+ webkit_web_view_get_snapshot(m_webView, WEBKIT_SNAPSHOT_REGION_VISIBLE, WEBKIT_SNAPSHOT_OPTIONS_NONE, cancellable.get(), reinterpret_cast<GAsyncReadyCallback>(onSnapshotCancelledReady), this);
+ g_cancellable_cancel(cancellable.get());
+ g_main_loop_run(m_mainLoop);
+
+ return true;
+ }
+
+ cairo_surface_t* m_surface;
+};
+
+static gboolean cairoSurfacesEqual(cairo_surface_t* s1, cairo_surface_t* s2)
+{
+ return (cairo_image_surface_get_format(s1) == cairo_image_surface_get_format(s2)
+ && cairo_image_surface_get_width(s1) == cairo_image_surface_get_width(s2)
+ && cairo_image_surface_get_height(s1) == cairo_image_surface_get_height(s2)
+ && cairo_image_surface_get_stride(s1) == cairo_image_surface_get_stride(s2)
+ && !memcmp(const_cast<const void*>(reinterpret_cast<void*>(cairo_image_surface_get_data(s1))),
+ const_cast<const void*>(reinterpret_cast<void*>(cairo_image_surface_get_data(s2))),
+ cairo_image_surface_get_height(s1)*cairo_image_surface_get_stride(s1)));
+}
+
+static void testWebViewSnapshot(SnapshotWebViewTest* test, gconstpointer)
+{
+ test->loadHtml("<html><body><p>Whatever</p></body></html>", 0);
+ test->waitUntilLoadFinished();
+
+ // WebView not visible.
+ cairo_surface_t* surface1 = test->waitForSnapshot(WEBKIT_SNAPSHOT_REGION_VISIBLE, WEBKIT_SNAPSHOT_OPTIONS_NONE);
+ g_assert(!surface1);
+
+ // Show surface, resize to 50x50, try again.
+ test->showInWindowAndWaitUntilMapped();
+ test->resizeView(50, 50);
+ surface1 = test->waitForSnapshot(WEBKIT_SNAPSHOT_REGION_VISIBLE, WEBKIT_SNAPSHOT_OPTIONS_NONE);
+ g_assert(surface1);
+
+ // obtained surface should be at the most 50x50. Store the size
+ // for comparison later.
+ int width = cairo_image_surface_get_width(surface1);
+ int height = cairo_image_surface_get_height(surface1);
+ g_assert_cmpint(width, <=, 50);
+ g_assert_cmpint(height, <=, 50);
+
+ cairo_surface_destroy(surface1);
+
+ // Select all text in the WebView, request a snapshot ignoring selection.
+ test->selectAll();
+ surface1 = test->waitForSnapshot(WEBKIT_SNAPSHOT_REGION_VISIBLE, WEBKIT_SNAPSHOT_OPTIONS_NONE);
+ g_assert(surface1);
+ g_assert_cmpint(cairo_image_surface_get_width(surface1), ==, width);
+ g_assert_cmpint(cairo_image_surface_get_height(surface1), ==, height);
+
+ // Create identical surface.
+ cairo_surface_t* surface2 = test->waitForSnapshot(WEBKIT_SNAPSHOT_REGION_VISIBLE, WEBKIT_SNAPSHOT_OPTIONS_NONE);
+ g_assert(surface2);
+
+ // Compare these two, they should be identical.
+ g_assert(cairoSurfacesEqual(surface1, surface2));
+ cairo_surface_destroy(surface2);
+
+ // Request a new snapshot, including the selection this time. The
+ // size should be the same but the result must be different to the
+ // one previously obtained.
+ surface2 = test->waitForSnapshot(WEBKIT_SNAPSHOT_REGION_VISIBLE, WEBKIT_SNAPSHOT_OPTIONS_INCLUDE_SELECTION_HIGHLIGHTING);
+ g_assert(surface2);
+ g_assert_cmpint(cairo_image_surface_get_width(surface2), ==, width);
+ g_assert_cmpint(cairo_image_surface_get_height(surface2), ==, height);
+ g_assert(!cairoSurfacesEqual(surface1, surface2));
+ cairo_surface_destroy(surface2);
+
+ // Request a snapshot of the whole document in the WebView. The
+ // result should be different from the size obtained previously.
+ surface2 = test->waitForSnapshot(WEBKIT_SNAPSHOT_REGION_FULL_DOCUMENT, WEBKIT_SNAPSHOT_OPTIONS_NONE);
+ g_assert(surface2);
+ g_assert_cmpint(cairo_image_surface_get_width(surface2), >, width);
+ g_assert_cmpint(cairo_image_surface_get_height(surface2), >, height);
+ g_assert(!cairoSurfacesEqual(surface1, surface2));
+
+ cairo_surface_destroy(surface1);
+ cairo_surface_destroy(surface2);
+
+ g_assert(test->getSnapshotAndCancel());
+}
+
void beforeAll()
{
WebViewTest::add("WebKitWebView", "default-context", testWebViewDefaultContext);
@@ -1166,6 +1295,7 @@
FormClientTest::add("WebKitWebView", "submit-form", testWebViewSubmitForm);
SaveWebViewTest::add("WebKitWebView", "save", testWebViewSave);
WebViewTest::add("WebKitWebView", "view-mode", testWebViewMode);
+ SnapshotWebViewTest::add("WebKitWebView", "snapshot", testWebViewSnapshot);
WebViewTest::add("WebKitWebView", "page-visibility", testWebViewPageVisibility);
}
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp 2013-04-16 18:29:43 UTC (rev 148526)
@@ -207,6 +207,11 @@
gtk_widget_size_allocate(GTK_WIDGET(m_webView), &allocation);
}
+void WebViewTest::selectAll()
+{
+ webkit_web_view_execute_editing_command(m_webView, "SelectAll");
+}
+
static void resourceGetDataCallback(GObject* object, GAsyncResult* result, gpointer userData)
{
size_t dataSize;
Modified: trunk/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h (148525 => 148526)
--- trunk/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h 2013-04-16 18:29:43 UTC (rev 148526)
@@ -49,6 +49,7 @@
void showInWindow(GtkWindowType = GTK_WINDOW_POPUP);
void showInWindowAndWaitUntilMapped(GtkWindowType = GTK_WINDOW_POPUP);
void resizeView(int width, int height);
+ void selectAll();
const char* mainResourceData(size_t& mainResourceDataSize);
void mouseMoveTo(int x, int y, unsigned int mouseModifiers = 0);
Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebExtension.cpp (148525 => 148526)
--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebExtension.cpp 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebExtension.cpp 2013-04-16 18:29:43 UTC (rev 148526)
@@ -105,6 +105,13 @@
webkitWebExtensionDidReceiveMessage(WEBKIT_WEB_EXTENSION(clientInfo), toImpl(name)->string(), *toImpl(static_cast<WKDictionaryRef>(messageBody)));
}
+static void didReceiveMessageToPage(WKBundleRef bundle, WKBundlePageRef page, WKStringRef name, WKTypeRef messageBody, const void* clientInfo)
+{
+ ASSERT(WKGetTypeID(messageBody) == WKDictionaryGetTypeID());
+ if (WebKitWebPage* webPage = WEBKIT_WEB_EXTENSION(clientInfo)->priv->pages.get(toImpl(page)).get())
+ webkitWebPageDidReceiveMessage(webPage, toImpl(name)->string(), *toImpl(static_cast<WKDictionaryRef>(messageBody)));
+}
+
WebKitWebExtension* webkitWebExtensionCreate(InjectedBundle* bundle)
{
WebKitWebExtension* extension = WEBKIT_WEB_EXTENSION(g_object_new(WEBKIT_TYPE_WEB_EXTENSION, NULL));
@@ -116,7 +123,7 @@
willDestroyPage,
0, // didInitializePageGroup
didReceiveMessage,
- 0 // didReceiveMessageToPage
+ didReceiveMessageToPage
};
WKBundleSetClient(toAPI(bundle), &wkBundleClient);
Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp (148525 => 148526)
--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp 2013-04-16 18:29:43 UTC (rev 148526)
@@ -20,16 +20,19 @@
#include "config.h"
#include "WebKitWebPage.h"
+#include "ImageOptions.h"
#include "ImmutableDictionary.h"
#include "InjectedBundle.h"
#include "WKBundleAPICast.h"
#include "WKBundleFrame.h"
#include "WebFrame.h"
+#include "WebImage.h"
#include "WebKitDOMDocumentPrivate.h"
#include "WebKitPrivate.h"
#include "WebKitWebPagePrivate.h"
#include "WebProcess.h"
#include <WebCore/Frame.h>
+#include <WebCore/FrameView.h>
using namespace WebKit;
using namespace WebCore;
@@ -196,6 +199,40 @@
return page;
}
+void webkitWebPageDidReceiveMessage(WebKitWebPage* page, const String& messageName, ImmutableDictionary& message)
+{
+ if (messageName == String("GetSnapshot")) {
+ SnapshotOptions snapshotOptions = static_cast<SnapshotOptions>(static_cast<WebUInt64*>(message.get("SnapshotOptions"))->value());
+ uint64_t callbackID = static_cast<WebUInt64*>(message.get("CallbackID"))->value();
+ SnapshotRegion region = static_cast<SnapshotRegion>(static_cast<WebUInt64*>(message.get("SnapshotRegion"))->value());
+
+ RefPtr<WebImage> snapshotImage;
+ WebPage* webPage = page->priv->webPage;
+ if (WebCore::FrameView* frameView = webPage->mainFrameView()) {
+ WebCore::IntRect snapshotRect;
+ switch (region) {
+ case SnapshotRegionVisible:
+ snapshotRect = frameView->visibleContentRect(WebCore::ScrollableArea::ExcludeScrollbars);
+ break;
+ case SnapshotRegionFullDocument:
+ snapshotRect = WebCore::IntRect(WebCore::IntPoint(0, 0), frameView->contentsSize());
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ if (!snapshotRect.isEmpty())
+ snapshotImage = webPage->scaledSnapshotWithOptions(snapshotRect, 1, snapshotOptions | SnapshotOptionsShareable);
+ }
+
+ ImmutableDictionary::MapType messageReply;
+ messageReply.set("Page", webPage);
+ messageReply.set("CallbackID", WebUInt64::create(callbackID));
+ messageReply.set("Snapshot", snapshotImage);
+ WebProcess::shared().injectedBundle()->postMessage("WebPage.DidGetSnapshot", ImmutableDictionary::adopt(messageReply).get());
+ } else
+ ASSERT_NOT_REACHED();
+}
+
/**
* webkit_web_page_get_dom_document:
* @web_page: a #WebKitWebPage
Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPagePrivate.h (148525 => 148526)
--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPagePrivate.h 2013-04-16 18:25:38 UTC (rev 148525)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPagePrivate.h 2013-04-16 18:29:43 UTC (rev 148526)
@@ -20,9 +20,11 @@
#ifndef WebKitWebPagePrivate_h
#define WebKitWebPagePrivate_h
+#include "ImmutableDictionary.h"
#include "WebKitWebPage.h"
#include "WebPage.h"
WebKitWebPage* webkitWebPageCreate(WebKit::WebPage*);
+void webkitWebPageDidReceiveMessage(WebKitWebPage*, const String& messageName, WebKit::ImmutableDictionary& message);
#endif // WebKitWebPagePrivate_h