<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[175694] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/175694">175694</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2014-11-06 07:08:07 -0800 (Thu, 06 Nov 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[GTK] Add context menu API to Web Process Extensions
https://bugs.webkit.org/show_bug.cgi?id=138311

Reviewed by Gustavo Noronha Silva.

Source/WebKit2:

Add WebKitWebPage::context-menu signal, similar to the
WebKitWebView one, but that receives a WebKitWebHitTestResult, a
class that extends WebKitTestResult to provide the WebKitDOMNode
from the Web Process Extensions API. This makes WebKitContextMenu,
WebKitContextMenuItem and WebKitTestResult classes shared between
UI and Web Extensions APIs. In addition to be able to customize
the context menu, it also provides API to set user data, as a
GVariant, in the Web Process that is sent to the UI Process.

* PlatformGTK.cmake: Add new files.
* UIProcess/API/gtk/WebKitContextMenu.cpp:
(webkit_context_menu_set_user_data): Add user data to the context
menu as a GVariant.
(webkit_context_menu_get_user_data): Get the user data previously
set with webkit_context_menu_set_user_data() either from the Web
or UI processes.
* UIProcess/API/gtk/WebKitContextMenu.h:
* UIProcess/API/gtk/WebKitContextMenuActions.h:
* UIProcess/API/gtk/WebKitContextMenuClient.cpp:
(getContextMenuFromProposedMenu): Convert the received user data
into a GVariant and pass it to webkitWebViewPopulateContextMenu().
* UIProcess/API/gtk/WebKitContextMenuItem.h:
* UIProcess/API/gtk/WebKitForwardDeclarations.h:
* UIProcess/API/gtk/WebKitHitTestResult.h:
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkitWebViewPopulateContextMenu): Set the user data received
from the Web Process to the WebKitContextMenu before emitting
WebKitWebView::context-menu.
* UIProcess/API/gtk/WebKitWebViewPrivate.h:
* UIProcess/API/gtk/docs/webkit2gtk-docs.sgml: Add new section for WebKitWebHitTestResult.
* UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Add new symbols.
* UIProcess/API/gtk/docs/webkit2gtk.types: Add webkit_web_hit_test_result_get_type.
* WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.cpp: Added.
(webkitWebHitTestResultGetProperty): Add getter for node property.
(webkitWebHitTestResultSetProperty): Add setter for node property.
(webkit_web_hit_test_result_class_init): Add node property.
(webkitWebHitTestResultCreate): Create a new
WebKitWebHitTestResult for the given InjectedBundleHitTestResult.
(webkit_web_hit_test_result_get_node): Return the WebKitDOMNode.
* WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.h: Added.
* WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResultPrivate.h: Added.
* WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp:
(getContextMenuFromDefaultMenu): Build a WebKitContextMenu and
WebKitWebHitTestResult and emit WebKitWebPage::context-menu signal.
(webkit_web_page_class_init): Add WebKitWebPage::context-menu signal.
(webkitWebPageCreate): Add implementation for getContextMenuFromDefaultMenu.
* WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h:

Tools:

Add tests cases for WebKitWebPage::context-menu signal.

* TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp:
(testContextMenuWebExtensionMenu):
(testContextMenuWebExtensionNode):
(beforeAll):
* TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp:
(serializeContextMenu):
(serializeNode):
(contextMenuCallback):
(pageCreatedCallback):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PlatformGTKcmake">trunk/Source/WebKit2/PlatformGTK.cmake</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenucpp">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenuh">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenuActionsh">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenuClientcpp">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuClient.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenuItemh">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitForwardDeclarationsh">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitForwardDeclarations.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitHitTestResulth">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitHitTestResult.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitWebViewcpp">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkWebKitWebViewPrivateh">trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtkdocssgml">trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtksectionstxt">trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtktypes">trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types</a></li>
<li><a href="#trunkSourceWebKit2WebProcessInjectedBundleAPIgtkWebKitWebPagecpp">trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessInjectedBundleAPIgtkwebkitwebextensionh">trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2GtkTestContextMenucpp">trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2GtkWebExtensionTestcpp">trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2WebProcessInjectedBundleAPIgtkWebKitWebHitTestResultcpp">trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessInjectedBundleAPIgtkWebKitWebHitTestResulth">trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessInjectedBundleAPIgtkWebKitWebHitTestResultPrivateh">trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResultPrivate.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/ChangeLog        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -1,3 +1,58 @@
</span><ins>+2014-11-06  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [GTK] Add context menu API to Web Process Extensions
+        https://bugs.webkit.org/show_bug.cgi?id=138311
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Add WebKitWebPage::context-menu signal, similar to the
+        WebKitWebView one, but that receives a WebKitWebHitTestResult, a
+        class that extends WebKitTestResult to provide the WebKitDOMNode
+        from the Web Process Extensions API. This makes WebKitContextMenu,
+        WebKitContextMenuItem and WebKitTestResult classes shared between
+        UI and Web Extensions APIs. In addition to be able to customize
+        the context menu, it also provides API to set user data, as a
+        GVariant, in the Web Process that is sent to the UI Process.
+
+        * PlatformGTK.cmake: Add new files.
+        * UIProcess/API/gtk/WebKitContextMenu.cpp:
+        (webkit_context_menu_set_user_data): Add user data to the context
+        menu as a GVariant.
+        (webkit_context_menu_get_user_data): Get the user data previously
+        set with webkit_context_menu_set_user_data() either from the Web
+        or UI processes.
+        * UIProcess/API/gtk/WebKitContextMenu.h:
+        * UIProcess/API/gtk/WebKitContextMenuActions.h:
+        * UIProcess/API/gtk/WebKitContextMenuClient.cpp:
+        (getContextMenuFromProposedMenu): Convert the received user data
+        into a GVariant and pass it to webkitWebViewPopulateContextMenu().
+        * UIProcess/API/gtk/WebKitContextMenuItem.h:
+        * UIProcess/API/gtk/WebKitForwardDeclarations.h:
+        * UIProcess/API/gtk/WebKitHitTestResult.h:
+        * UIProcess/API/gtk/WebKitWebView.cpp:
+        (webkitWebViewPopulateContextMenu): Set the user data received
+        from the Web Process to the WebKitContextMenu before emitting
+        WebKitWebView::context-menu.
+        * UIProcess/API/gtk/WebKitWebViewPrivate.h:
+        * UIProcess/API/gtk/docs/webkit2gtk-docs.sgml: Add new section for WebKitWebHitTestResult.
+        * UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Add new symbols.
+        * UIProcess/API/gtk/docs/webkit2gtk.types: Add webkit_web_hit_test_result_get_type.
+        * WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.cpp: Added.
+        (webkitWebHitTestResultGetProperty): Add getter for node property.
+        (webkitWebHitTestResultSetProperty): Add setter for node property.
+        (webkit_web_hit_test_result_class_init): Add node property.
+        (webkitWebHitTestResultCreate): Create a new
+        WebKitWebHitTestResult for the given InjectedBundleHitTestResult.
+        (webkit_web_hit_test_result_get_node): Return the WebKitDOMNode.
+        * WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.h: Added.
+        * WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResultPrivate.h: Added.
+        * WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp:
+        (getContextMenuFromDefaultMenu): Build a WebKitContextMenu and
+        WebKitWebHitTestResult and emit WebKitWebPage::context-menu signal.
+        (webkit_web_page_class_init): Add WebKitWebPage::context-menu signal.
+        (webkitWebPageCreate): Add implementation for getContextMenuFromDefaultMenu.
+        * WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h:
+
</ins><span class="cx"> 2014-11-06  Ryuan Choi  &lt;ryuan.choi@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [EFL] Remove m_scrollPosition from CoordinatedGraphicsScene
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformGTKcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PlatformGTK.cmake (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PlatformGTK.cmake        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/PlatformGTK.cmake        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -274,6 +274,7 @@
</span><span class="cx">     WebProcess/InjectedBundle/API/gtk/WebKitFrame.cpp
</span><span class="cx">     WebProcess/InjectedBundle/API/gtk/WebKitScriptWorld.cpp
</span><span class="cx">     WebProcess/InjectedBundle/API/gtk/WebKitWebExtension.cpp
</span><ins>+    WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.cpp
</ins><span class="cx">     WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp
</span><span class="cx"> 
</span><span class="cx">     WebProcess/InjectedBundle/gtk/InjectedBundleGtk.cpp
</span><span class="lines">@@ -372,6 +373,7 @@
</span><span class="cx">     ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk/WebKitFrame.h
</span><span class="cx">     ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk/WebKitScriptWorld.h
</span><span class="cx">     ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk/WebKitWebExtension.h
</span><ins>+    ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.h
</ins><span class="cx">     ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.h
</span><span class="cx">     ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h
</span><span class="cx"> )
</span><span class="lines">@@ -797,6 +799,10 @@
</span><span class="cx">         -I${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk
</span><span class="cx">         ${GObjectDOMBindings_GIR_HEADERS}
</span><span class="cx">         ${WebKit2WebExtension_INSTALLED_HEADERS}
</span><ins>+        ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitContextMenu.h
+        ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitContextMenuActions.h
+        ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitContextMenuItem.h
+        ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitHitTestResult.h
</ins><span class="cx">         ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitURIRequest.h
</span><span class="cx">         ${WEBKIT2_DIR}/UIProcess/API/gtk/WebKitURIResponse.h
</span><span class="cx">         ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk/*.cpp
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenucpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.cpp (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.cpp        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.cpp        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -24,6 +24,7 @@
</span><span class="cx"> #include &quot;WebContextMenuItem.h&quot;
</span><span class="cx"> #include &quot;WebKitContextMenuItemPrivate.h&quot;
</span><span class="cx"> #include &quot;WebKitContextMenuPrivate.h&quot;
</span><ins>+#include &lt;wtf/gobject/GRefPtr.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> using namespace WebKit;
</span><span class="cx"> using namespace WebCore;
</span><span class="lines">@@ -50,6 +51,7 @@
</span><span class="cx"> struct _WebKitContextMenuPrivate {
</span><span class="cx">     GList* items;
</span><span class="cx">     WebKitContextMenuItem* parentItem;
</span><ins>+    GRefPtr&lt;GVariant&gt; userData;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WEBKIT_DEFINE_TYPE(WebKitContextMenu, webkit_context_menu, G_TYPE_OBJECT)
</span><span class="lines">@@ -316,3 +318,41 @@
</span><span class="cx">     g_list_free_full(menu-&gt;priv-&gt;items, reinterpret_cast&lt;GDestroyNotify&gt;(g_object_unref));
</span><span class="cx">     menu-&gt;priv-&gt;items = 0;
</span><span class="cx"> }
</span><ins>+
+/**
+ * webkit_context_menu_set_user_data:
+ * @menu: a #WebKitContextMenu
+ * @user_data: a #GVariant
+ *
+ * Sets user data to @menu.
+ * This function can be used from a Web Process extension to set user data
+ * that can be retrieved from the UI Process using webkit_context_menu_get_user_data().
+ *
+ * Since: 2.8
+ */
+void webkit_context_menu_set_user_data(WebKitContextMenu* menu, GVariant* userData)
+{
+    g_return_if_fail(WEBKIT_IS_CONTEXT_MENU(menu));
+    g_return_if_fail(userData);
+
+    menu-&gt;priv-&gt;userData = userData;
+}
+
+/**
+ * webkit_context_menu_get_user_data:
+ * @menu: a #WebKitContextMenu
+ *
+ * Gets the user data of @menu.
+ * This function can be used from the UI Process to get user data previously set
+ * from the Web Process with webkit_context_menu_set_user_data().
+ *
+ * Returns: (transfer none): the user data of @menu, or %NULL if @menu doesn't have user data
+ *
+ * Since: 2.8
+ */
+GVariant* webkit_context_menu_get_user_data(WebKitContextMenu* menu)
+{
+    g_return_val_if_fail(WEBKIT_IS_CONTEXT_MENU(menu), nullptr);
+
+    return menu-&gt;priv-&gt;userData.get();
+}
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenuh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.h (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.h        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenu.h        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx">  * Boston, MA 02110-1301, USA.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION)
</del><ins>+#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION) &amp;&amp; !defined(__WEBKIT_WEB_EXTENSION_H_INSIDE__)
</ins><span class="cx"> #error &quot;Only &lt;webkit2/webkit2.h&gt; can be included directly.&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="lines">@@ -105,6 +105,13 @@
</span><span class="cx"> WEBKIT_API void
</span><span class="cx"> webkit_context_menu_remove_all           (WebKitContextMenu     *menu);
</span><span class="cx"> 
</span><ins>+WEBKIT_API void
+webkit_context_menu_set_user_data        (WebKitContextMenu     *menu,
+                                          GVariant              *user_data);
+
+WEBKIT_API GVariant *
+webkit_context_menu_get_user_data        (WebKitContextMenu     *menu);
+
</ins><span class="cx"> G_END_DECLS
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenuActionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.h (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.h        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuActions.h        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx">  * Boston, MA 02110-1301, USA.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION)
</del><ins>+#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION) &amp;&amp; !defined(__WEBKIT_WEB_EXTENSION_H_INSIDE__)
</ins><span class="cx"> #error &quot;Only &lt;webkit2/webkit2.h&gt; can be included directly.&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenuClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuClient.cpp (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuClient.cpp        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuClient.cpp        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -26,9 +26,15 @@
</span><span class="cx"> 
</span><span class="cx"> using namespace WebKit;
</span><span class="cx"> 
</span><del>-static void getContextMenuFromProposedMenu(WKPageRef, WKArrayRef proposedMenu, WKArrayRef*, WKHitTestResultRef hitTestResult, WKTypeRef /* userData */, const void* clientInfo)
</del><ins>+static void getContextMenuFromProposedMenu(WKPageRef, WKArrayRef proposedMenu, WKArrayRef*, WKHitTestResultRef hitTestResult, WKTypeRef userData, const void* clientInfo)
</ins><span class="cx"> {
</span><del>-    webkitWebViewPopulateContextMenu(WEBKIT_WEB_VIEW(clientInfo), toImpl(proposedMenu), toImpl(hitTestResult));
</del><ins>+    GRefPtr&lt;GVariant&gt; variant;
+    if (userData) {
+        ASSERT(WKGetTypeID(userData) == WKStringGetTypeID());
+        CString userDataString = toImpl(static_cast&lt;WKStringRef&gt;(userData))-&gt;string().utf8();
+        variant = adoptGRef(g_variant_parse(nullptr, userDataString.data(), userDataString.data() + userDataString.length(), nullptr, nullptr));
+    }
+    webkitWebViewPopulateContextMenu(WEBKIT_WEB_VIEW(clientInfo), toImpl(proposedMenu), toImpl(hitTestResult), variant.get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void attachContextMenuClientToView(WebKitWebView* webView)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitContextMenuItemh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.h (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.h        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitContextMenuItem.h        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx">  * Boston, MA 02110-1301, USA.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION)
</del><ins>+#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION) &amp;&amp; !defined(__WEBKIT_WEB_EXTENSION_H_INSIDE__)
</ins><span class="cx"> #error &quot;Only &lt;webkit2/webkit2.h&gt; can be included directly.&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitForwardDeclarationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitForwardDeclarations.h (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitForwardDeclarations.h        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitForwardDeclarations.h        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -23,7 +23,7 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION)
</del><ins>+#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION) &amp;&amp; !defined(__WEBKIT_WEB_EXTENSION_H_INSIDE__)
</ins><span class="cx"> #error &quot;Only &lt;webkit2/webkit2.h&gt; can be included directly.&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitHitTestResulth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitHitTestResult.h (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitHitTestResult.h        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitHitTestResult.h        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -17,7 +17,7 @@
</span><span class="cx">  * Boston, MA 02110-1301, USA.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION)
</del><ins>+#if !defined(__WEBKIT2_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION) &amp;&amp; !defined(__WEBKIT_WEB_EXTENSION_H_INSIDE__)
</ins><span class="cx"> #error &quot;Only &lt;webkit2/webkit2.h&gt; can be included directly.&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitWebViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -1891,7 +1891,7 @@
</span><span class="cx">     g_signal_emit(webView, signals[CONTEXT_MENU_DISMISSED], 0, NULL);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void webkitWebViewPopulateContextMenu(WebKitWebView* webView, API::Array* proposedMenu, WebHitTestResult* webHitTestResult)
</del><ins>+void webkitWebViewPopulateContextMenu(WebKitWebView* webView, API::Array* proposedMenu, WebHitTestResult* webHitTestResult, GVariant* userData)
</ins><span class="cx"> {
</span><span class="cx">     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView);
</span><span class="cx">     WebContextMenuProxyGtk* contextMenuProxy = webkitWebViewBaseGetActiveContextMenuProxy(webViewBase);
</span><span class="lines">@@ -1917,6 +1917,9 @@
</span><span class="cx">     GRefPtr&lt;WebKitHitTestResult&gt; hitTestResult = adoptGRef(webkitHitTestResultCreate(data));
</span><span class="cx">     GUniquePtr&lt;GdkEvent&gt; contextMenuEvent(webkitWebViewBaseTakeContextMenuEvent(webViewBase));
</span><span class="cx"> 
</span><ins>+    if (userData)
+        webkit_context_menu_set_user_data(WEBKIT_CONTEXT_MENU(contextMenu.get()), userData);
+
</ins><span class="cx">     gboolean returnValue;
</span><span class="cx">     g_signal_emit(webView, signals[CONTEXT_MENU], 0, contextMenu.get(), contextMenuEvent.get(), hitTestResult.get(), &amp;returnValue);
</span><span class="cx">     if (returnValue)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkWebKitWebViewPrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -53,7 +53,7 @@
</span><span class="cx"> void webkitWebViewRemoveLoadingWebResource(WebKitWebView*, uint64_t resourceIdentifier);
</span><span class="cx"> bool webkitWebViewEnterFullScreen(WebKitWebView*);
</span><span class="cx"> bool webkitWebViewLeaveFullScreen(WebKitWebView*);
</span><del>-void webkitWebViewPopulateContextMenu(WebKitWebView*, API::Array* proposedMenu, WebKit::WebHitTestResult*);
</del><ins>+void webkitWebViewPopulateContextMenu(WebKitWebView*, API::Array* proposedMenu, WebKit::WebHitTestResult*, GVariant*);
</ins><span class="cx"> void webkitWebViewSubmitFormRequest(WebKitWebView*, WebKitFormSubmissionRequest*);
</span><span class="cx"> void webkitWebViewHandleAuthenticationChallenge(WebKitWebView*, WebKit::AuthenticationChallengeProxy*);
</span><span class="cx"> void webkitWebViewInsecureContentDetected(WebKitWebView*, WebKitInsecureContentEvent);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtkdocssgml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">     &lt;xi:include href=&quot;xml/WebKitWebPage.xml&quot;/&gt;
</span><span class="cx">     &lt;xi:include href=&quot;xml/WebKitFrame.xml&quot;/&gt;
</span><span class="cx">     &lt;xi:include href=&quot;xml/WebKitScriptWorld.xml&quot;/&gt;
</span><ins>+    &lt;xi:include href=&quot;xml/WebKitWebHitTestResult.xml&quot;/&gt;
</ins><span class="cx">   &lt;/chapter&gt;
</span><span class="cx"> 
</span><span class="cx">   &lt;index id=&quot;index-all&quot;&gt;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtksectionstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -982,6 +982,8 @@
</span><span class="cx"> webkit_context_menu_get_item_at_position
</span><span class="cx"> webkit_context_menu_remove
</span><span class="cx"> webkit_context_menu_remove_all
</span><ins>+webkit_context_menu_set_user_data
+webkit_context_menu_get_user_data
</ins><span class="cx"> 
</span><span class="cx"> &lt;SUBSECTION Standard&gt;
</span><span class="cx"> WebKitContextMenuClass
</span><span class="lines">@@ -1160,3 +1162,22 @@
</span><span class="cx"> WebKitScriptWorldPrivate
</span><span class="cx"> webkit_script_world_get_type
</span><span class="cx"> &lt;/SECTION&gt;
</span><ins>+
+&lt;SECTION&gt;
+&lt;FILE&gt;WebKitWebHitTestResult&lt;/FILE&gt;
+WebKitWebHitTestResult
+webkit_web_hit_test_result_get_node
+
+&lt;SUBSECTION Standard&gt;
+WebKitWebHitTestResultClass
+WEBKIT_TYPE_WEB_HIT_TEST_RESULT
+WEBKIT_WEB_HIT_TEST_RESULT
+WEBKIT_IS_WEB_HIT_TEST_RESULT
+WEBKIT_WEB_HIT_TEST_RESULT_CLASS
+WEBKIT_IS_WEB_HIT_TEST_RESULT_CLASS
+WEBKIT_WEB_HIT_TEST_RESULT_GET_CLASS
+
+&lt;SUBSECTION Private&gt;
+WebKitWebHitTestResultPrivate
+webkit_web_hit_test_result_get_type
+&lt;/SECTION&gt;
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIgtkdocswebkit2gtktypes"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -28,3 +28,4 @@
</span><span class="cx"> webkit_frame_get_type
</span><span class="cx"> webkit_certificate_info_get_type
</span><span class="cx"> webkit_user_content_manager_get_type
</span><ins>+webkit_web_hit_test_result_get_type
</ins></span></pre></div>
<a id="trunkSourceWebKit2WebProcessInjectedBundleAPIgtkWebKitWebHitTestResultcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.cpp (0 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.cpp                                (rev 0)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.cpp        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -0,0 +1,151 @@
</span><ins>+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;WebKitWebHitTestResult.h&quot;
+
+#include &quot;InjectedBundleHitTestResult.h&quot;
+#include &quot;WebKitDOMNodePrivate.h&quot;
+#include &quot;WebKitPrivate.h&quot;
+#include &quot;WebKitWebHitTestResultPrivate.h&quot;
+#include &lt;glib/gi18n-lib.h&gt;
+#include &lt;wtf/gobject/GRefPtr.h&gt;
+#include &lt;wtf/text/CString.h&gt;
+
+using namespace WebKit;
+using namespace WebCore;
+
+/**
+ * SECTION: WebKitWebHitTestResult
+ * @Short_description: Result of a Hit Test (Web Process Extensions)
+ * @Title: WebKitWebHitTestResult
+ * @See_also: #WebKitHitTestResult, #WebKitWebPage
+ *
+ * WebKitWebHitTestResult extends #WebKitHitTestResult to provide information
+ * about the #WebKitDOMNode in the coordinates of the Hit Test.
+ *
+ * Since: 2.8
+ */
+
+enum {
+    PROP_0,
+
+    PROP_NODE
+};
+
+struct _WebKitWebHitTestResultPrivate {
+    GRefPtr&lt;WebKitDOMNode&gt; node;
+};
+
+WEBKIT_DEFINE_TYPE(WebKitWebHitTestResult, webkit_web_hit_test_result, WEBKIT_TYPE_HIT_TEST_RESULT)
+
+static void webkitWebHitTestResultGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
+{
+    WebKitWebHitTestResult* webHitTestResult = WEBKIT_WEB_HIT_TEST_RESULT(object);
+
+    switch (propId) {
+    case PROP_NODE:
+        g_value_set_object(value, webkit_web_hit_test_result_get_node(webHitTestResult));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
+    }
+}
+
+static void webkitWebHitTestResultSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec)
+{
+    WebKitWebHitTestResult* webHitTestResult = WEBKIT_WEB_HIT_TEST_RESULT(object);
+
+    switch (propId) {
+    case PROP_NODE: {
+        gpointer node = g_value_get_object(value);
+        webHitTestResult-&gt;priv-&gt;node = node ? WEBKIT_DOM_NODE(node) : nullptr;
+        break;
+    }
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
+    }
+}
+
+static void webkit_web_hit_test_result_class_init(WebKitWebHitTestResultClass* klass)
+{
+    GObjectClass* gObjectClass = G_OBJECT_CLASS(klass);
+
+    gObjectClass-&gt;get_property = webkitWebHitTestResultGetProperty;
+    gObjectClass-&gt;set_property = webkitWebHitTestResultSetProperty;
+
+    /**
+     * WebKitWebHitTestResult:node:
+     *
+     * The #WebKitDOMNode
+     */
+    g_object_class_install_property(
+        gObjectClass,
+        PROP_NODE,
+        g_param_spec_object(
+            &quot;node&quot;,
+            _(&quot;Node&quot;),
+            _(&quot;The WebKitDOMNode&quot;),
+            WEBKIT_DOM_TYPE_NODE,
+            static_cast&lt;GParamFlags&gt;(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
+}
+
+WebKitWebHitTestResult* webkitWebHitTestResultCreate(const InjectedBundleHitTestResult&amp; hitTestResult)
+{
+    unsigned context = WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT;
+    if (!hitTestResult.absoluteLinkURL().isEmpty())
+        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK;
+    if (!hitTestResult.absoluteImageURL().isEmpty())
+        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE;
+    if (!hitTestResult.absoluteMediaURL().isEmpty())
+        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA;
+    if (hitTestResult.coreHitTestResult().isContentEditable())
+        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE;
+    if (hitTestResult.coreHitTestResult().scrollbar())
+        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_SCROLLBAR;
+    if (hitTestResult.isSelected())
+        context |= WEBKIT_HIT_TEST_RESULT_CONTEXT_SELECTION;
+
+    return WEBKIT_WEB_HIT_TEST_RESULT(g_object_new(WEBKIT_TYPE_WEB_HIT_TEST_RESULT,
+        &quot;context&quot;, context,
+        &quot;link-uri&quot;, context &amp; WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK ? hitTestResult.absoluteLinkURL().utf8().data() : nullptr,
+        &quot;image-uri&quot;, context &amp; WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE ? hitTestResult.absoluteImageURL().utf8().data() : nullptr,
+        &quot;media-uri&quot;, context &amp; WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA ? hitTestResult.absoluteMediaURL().utf8().data() : nullptr,
+        &quot;link-title&quot;, !hitTestResult.linkTitle().isEmpty() ? hitTestResult.linkTitle().utf8().data() : nullptr,
+        &quot;link-label&quot;, !hitTestResult.linkLabel().isEmpty() ? hitTestResult.linkLabel().utf8().data() : nullptr,
+        &quot;node&quot;, kit(hitTestResult.coreHitTestResult().innerNonSharedNode()),
+        nullptr));
+}
+
+/**
+ * webkit_web_hit_test_result_get_node:
+ * @hit_test_result: a #WebKitWebHitTestResult
+ *
+ * Get the #WebKitDOMNode in the coordinates of the Hit Test.
+ *
+ * Returns: (transfer none): a #WebKitDOMNode
+ *
+ * Since: 2.8
+ */
+WebKitDOMNode* webkit_web_hit_test_result_get_node(WebKitWebHitTestResult* webHitTestResult)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_HIT_TEST_RESULT(webHitTestResult), nullptr);
+
+    return webHitTestResult-&gt;priv-&gt;node.get();
+}
</ins></span></pre></div>
<a id="trunkSourceWebKit2WebProcessInjectedBundleAPIgtkWebKitWebHitTestResulth"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.h (0 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.h                                (rev 0)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResult.h        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -0,0 +1,68 @@
</span><ins>+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if !defined(__WEBKIT_WEB_EXTENSION_H_INSIDE__) &amp;&amp; !defined(WEBKIT2_COMPILATION)
+#error &quot;Only &lt;webkit2/webkit-web-extension.h&gt; can be included directly.&quot;
+#endif
+
+#ifndef WebKitWebHitTestResult_h
+#define WebKitWebHitTestResult_h
+
+#include &lt;glib-object.h&gt;
+#include &lt;webkit2/WebKitDefines.h&gt;
+#include &lt;webkit2/WebKitHitTestResult.h&gt;
+#include &lt;webkitdom/webkitdom.h&gt;
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_WEB_HIT_TEST_RESULT            (webkit_web_hit_test_result_get_type())
+#define WEBKIT_WEB_HIT_TEST_RESULT(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_HIT_TEST_RESULT, WebKitWebHitTestResult))
+#define WEBKIT_IS_WEB_HIT_TEST_RESULT(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_WEB_HIT_TEST_RESULT))
+#define WEBKIT_WEB_HIT_TEST_RESULT_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  WEBKIT_TYPE_WEB_HIT_TEST_RESULT, WebKitWebHitTestResultClass))
+#define WEBKIT_IS_WEB_HIT_TEST_RESULT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  WEBKIT_TYPE_WEB_HIT_TEST_RESULT))
+#define WEBKIT_WEB_HIT_TEST_RESULT_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  WEBKIT_TYPE_WEB_HIT_TEST_RESULT, WebKitWebHitTestResultClass))
+
+typedef struct _WebKitWebHitTestResult        WebKitWebHitTestResult;
+typedef struct _WebKitWebHitTestResultClass   WebKitWebHitTestResultClass;
+typedef struct _WebKitWebHitTestResultPrivate WebKitWebHitTestResultPrivate;
+
+struct _WebKitWebHitTestResult {
+    WebKitHitTestResult parent;
+
+    WebKitWebHitTestResultPrivate *priv;
+};
+
+struct _WebKitWebHitTestResultClass {
+    WebKitHitTestResultClass parent_class;
+
+    void (*_webkit_reserved0) (void);
+    void (*_webkit_reserved1) (void);
+    void (*_webkit_reserved2) (void);
+    void (*_webkit_reserved3) (void);
+};
+
+WEBKIT_API GType
+webkit_web_hit_test_result_get_type (void);
+
+WEBKIT_API WebKitDOMNode *
+webkit_web_hit_test_result_get_node (WebKitWebHitTestResult *hit_test_result);
+
+G_END_DECLS
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebKit2WebProcessInjectedBundleAPIgtkWebKitWebHitTestResultPrivateh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResultPrivate.h (0 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResultPrivate.h                                (rev 0)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebHitTestResultPrivate.h        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef WebKitWebHitTestResultPrivate_h
+#define WebKitWebHitTestResultPrivate_h
+
+#include &quot;InjectedBundleHitTestResult.h&quot;
+#include &quot;WebKitWebHitTestResult.h&quot;
+
+WebKitWebHitTestResult* webkitWebHitTestResultCreate(const WebKit::InjectedBundleHitTestResult&amp;);
+
+#endif // WebKitWebHitTestResultPrivate_h
</ins></span></pre></div>
<a id="trunkSourceWebKit2WebProcessInjectedBundleAPIgtkWebKitWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/WebKitWebPage.cpp        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -20,12 +20,15 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;WebKitWebPage.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;APIArray.h&quot;
</ins><span class="cx"> #include &quot;ImageOptions.h&quot;
</span><span class="cx"> #include &quot;ImmutableDictionary.h&quot;
</span><span class="cx"> #include &quot;InjectedBundle.h&quot;
</span><span class="cx"> #include &quot;WKBundleAPICast.h&quot;
</span><span class="cx"> #include &quot;WKBundleFrame.h&quot;
</span><ins>+#include &quot;WebContextMenuItem.h&quot;
</ins><span class="cx"> #include &quot;WebImage.h&quot;
</span><ins>+#include &quot;WebKitContextMenuPrivate.h&quot;
</ins><span class="cx"> #include &quot;WebKitDOMDocumentPrivate.h&quot;
</span><span class="cx"> #include &quot;WebKitFramePrivate.h&quot;
</span><span class="cx"> #include &quot;WebKitMarshal.h&quot;
</span><span class="lines">@@ -33,6 +36,7 @@
</span><span class="cx"> #include &quot;WebKitScriptWorldPrivate.h&quot;
</span><span class="cx"> #include &quot;WebKitURIRequestPrivate.h&quot;
</span><span class="cx"> #include &quot;WebKitURIResponsePrivate.h&quot;
</span><ins>+#include &quot;WebKitWebHitTestResultPrivate.h&quot;
</ins><span class="cx"> #include &quot;WebKitWebPagePrivate.h&quot;
</span><span class="cx"> #include &quot;WebProcess.h&quot;
</span><span class="cx"> #include &lt;WebCore/Document.h&gt;
</span><span class="lines">@@ -50,6 +54,7 @@
</span><span class="cx"> enum {
</span><span class="cx">     DOCUMENT_LOADED,
</span><span class="cx">     SEND_REQUEST,
</span><ins>+    CONTEXT_MENU,
</ins><span class="cx"> 
</span><span class="cx">     LAST_SIGNAL
</span><span class="cx"> };
</span><span class="lines">@@ -223,6 +228,36 @@
</span><span class="cx">     WebProcess::shared().injectedBundle()-&gt;postMessage(String::fromUTF8(&quot;WebPage.DidFailLoadForResource&quot;), ImmutableDictionary::create(WTF::move(message)).get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void getContextMenuFromDefaultMenu(WKBundlePageRef, WKBundleHitTestResultRef wkHitTestResult, WKArrayRef wkDefaultMenu, WKArrayRef* wkNewMenu, WKTypeRef* wkUserData, const void* clientInfo)
+{
+    GRefPtr&lt;WebKitContextMenu&gt; contextMenu = adoptGRef(webkitContextMenuCreate(toImpl(wkDefaultMenu)));
+    GRefPtr&lt;WebKitWebHitTestResult&gt; webHitTestResult = adoptGRef(webkitWebHitTestResultCreate(*toImpl(wkHitTestResult)));
+    gboolean returnValue;
+    g_signal_emit(WEBKIT_WEB_PAGE(clientInfo), signals[CONTEXT_MENU], 0, contextMenu.get(), webHitTestResult.get(), &amp;returnValue);
+    if (GVariant* userData = webkit_context_menu_get_user_data(contextMenu.get())) {
+        GUniquePtr&lt;gchar&gt; dataString(g_variant_print(userData, TRUE));
+        *wkUserData = static_cast&lt;WKTypeRef&gt;(WKStringCreateWithUTF8CString(dataString.get()));
+    }
+
+    if (!returnValue) {
+        WKRetain(wkDefaultMenu);
+        *wkNewMenu = wkDefaultMenu;
+        return;
+    }
+
+    Vector&lt;ContextMenuItem&gt; contextMenuItems;
+    webkitContextMenuPopulate(contextMenu.get(), contextMenuItems);
+
+    Vector&lt;RefPtr&lt;API::Object&gt;&gt; newMenuItems;
+    newMenuItems.reserveInitialCapacity(contextMenuItems.size());
+    for (const auto&amp; item : contextMenuItems)
+        newMenuItems.uncheckedAppend(WebContextMenuItem::create(item));
+
+    RefPtr&lt;API::Array&gt; array = API::Array::create(WTF::move(newMenuItems));
+    *wkNewMenu = toAPI(array.get());
+    WKRetain(*wkNewMenu);
+}
+
</ins><span class="cx"> static void webkitWebPageGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
</span><span class="cx"> {
</span><span class="cx">     WebKitWebPage* webPage = WEBKIT_WEB_PAGE(object);
</span><span class="lines">@@ -305,6 +340,36 @@
</span><span class="cx">         G_TYPE_BOOLEAN, 2,
</span><span class="cx">         WEBKIT_TYPE_URI_REQUEST,
</span><span class="cx">         WEBKIT_TYPE_URI_RESPONSE);
</span><ins>+
+    /**
+     * WebKitWebPage::context-menu:
+     * @web_page: the #WebKitWebPage on which the signal is emitted
+     * @context_menu: the proposed #WebKitContextMenu
+     * @hit_test_result: a #WebKitWebHitTestResult
+     *
+     * Emmited before a context menu is displayed in the UI Process to
+     * give the application a chance to customize the proposed menu,
+     * build its own context menu or pass user data to the UI Process.
+     * This signal is useful when the information available in the UI Process
+     * is not enough to build or customize the context menu, for example, to
+     * add menu entries depending on the #WebKitDOMNode at the coordinates of the
+     * @hit_test_result. Otherwise, it's recommened to use #WebKitWebView::context-menu
+     * signal instead.
+     *
+     * Returns: %TRUE if the proposed @context_menu has been modified, or %FALSE otherwise.
+     *
+     * Since: 2.8
+     */
+    signals[CONTEXT_MENU] = g_signal_new(
+        &quot;context-menu&quot;,
+        G_TYPE_FROM_CLASS(klass),
+        G_SIGNAL_RUN_LAST,
+        0,
+        g_signal_accumulator_true_handled, 0,
+        webkit_marshal_BOOLEAN__OBJECT_OBJECT,
+        G_TYPE_BOOLEAN, 2,
+        WEBKIT_TYPE_CONTEXT_MENU,
+        WEBKIT_TYPE_WEB_HIT_TEST_RESULT);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> WebKitWebPage* webkitWebPageCreate(WebPage* webPage)
</span><span class="lines">@@ -371,6 +436,15 @@
</span><span class="cx">     };
</span><span class="cx">     WKBundlePageSetResourceLoadClient(toAPI(webPage), &amp;resourceLoadClient.base);
</span><span class="cx"> 
</span><ins>+    WKBundlePageContextMenuClientV0 contextMenuClient = {
+        {
+            0, // version
+            page, // clientInfo
+        },
+        getContextMenuFromDefaultMenu,
+    };
+    WKBundlePageSetContextMenuClient(toAPI(webPage), &amp;contextMenuClient.base);
+
</ins><span class="cx">     return page;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessInjectedBundleAPIgtkwebkitwebextensionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Source/WebKit2/WebProcess/InjectedBundle/API/gtk/webkit-web-extension.h        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -26,12 +26,16 @@
</span><span class="cx"> 
</span><span class="cx"> #define __WEBKIT_WEB_EXTENSION_H_INSIDE__
</span><span class="cx"> 
</span><ins>+#include &lt;webkit2/WebKitContextMenu.h&gt;
+#include &lt;webkit2/WebKitContextMenuActions.h&gt;
+#include &lt;webkit2/WebKitContextMenuItem.h&gt;
</ins><span class="cx"> #include &lt;webkit2/WebKitFrame.h&gt;
</span><span class="cx"> #include &lt;webkit2/WebKitScriptWorld.h&gt;
</span><span class="cx"> #include &lt;webkit2/WebKitURIRequest.h&gt;
</span><span class="cx"> #include &lt;webkit2/WebKitURIResponse.h&gt;
</span><span class="cx"> #include &lt;webkit2/WebKitVersion.h&gt;
</span><span class="cx"> #include &lt;webkit2/WebKitWebExtension.h&gt;
</span><ins>+#include &lt;webkit2/WebKitWebHitTestResult.h&gt;
</ins><span class="cx"> #include &lt;webkit2/WebKitWebPage.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #undef __WEBKIT_WEB_EXTENSION_H_INSIDE__
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Tools/ChangeLog        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -1,3 +1,22 @@
</span><ins>+2014-11-06  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        [GTK] Add context menu API to Web Process Extensions
+        https://bugs.webkit.org/show_bug.cgi?id=138311
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Add tests cases for WebKitWebPage::context-menu signal.
+
+        * TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp:
+        (testContextMenuWebExtensionMenu):
+        (testContextMenuWebExtensionNode):
+        (beforeAll):
+        * TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp:
+        (serializeContextMenu):
+        (serializeNode):
+        (contextMenuCallback):
+        (pageCreatedCallback):
+
</ins><span class="cx"> 2014-11-06  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r175690.
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2GtkTestContextMenucpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -19,6 +19,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;WebViewTest.h&quot;
</span><ins>+#include &lt;wtf/Vector.h&gt;
</ins><span class="cx"> #include &lt;wtf/gobject/GRefPtr.h&gt;
</span><span class="cx"> 
</span><span class="cx"> class ContextMenuTest: public WebViewTest {
</span><span class="lines">@@ -882,8 +883,164 @@
</span><span class="cx">     g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) &amp;&amp; !gtk_widget_get_visible(item));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+class ContextMenuWebExtensionTest: public ContextMenuTest {
+public:
+    MAKE_GLIB_TEST_FIXTURE(ContextMenuWebExtensionTest);
+
+    void deserializeContextMenuFromUserData(GVariant* userData)
+    {
+        m_actions.clear();
+        if (!userData)
+            return;
+
+        GVariantIter iter;
+        g_variant_iter_init(&amp;iter, userData);
+        m_actions.reserveInitialCapacity(g_variant_iter_n_children(&amp;iter));
+
+        uint32_t item;
+        while (g_variant_iter_next(&amp;iter, &quot;u&quot;, &amp;item))
+            m_actions.uncheckedAppend(static_cast&lt;WebKitContextMenuAction&gt;(item));
+    }
+
+    bool contextMenu(WebKitContextMenu* menu, GdkEvent*, WebKitHitTestResult*)
+    {
+        deserializeContextMenuFromUserData(webkit_context_menu_get_user_data(menu));
+        GList* items = webkit_context_menu_get_items(menu);
+        g_assert_cmpuint(g_list_length(items), ==, m_actions.size());
+
+        unsigned actionIndex = 0;
+        for (GList* it = items; it; it = g_list_next(it)) {
+            WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(it-&gt;data);
+            g_assert_cmpuint(webkit_context_menu_item_get_stock_action(item), ==, m_actions[actionIndex++]);
+        }
+
+        quitMainLoop();
+
+        return true;
+    }
+
+    Vector&lt;WebKitContextMenuAction&gt; m_actions;
+};
+
+static void testContextMenuWebExtensionMenu(ContextMenuWebExtensionTest* test, gconstpointer)
+{
+    test-&gt;showInWindowAndWaitUntilMapped();
+    test-&gt;loadHtml(&quot;&lt;html&gt;&lt;body&gt;WebKitGTK+ Context menu tests&lt;br&gt;&quot;
+        &quot;&lt;a style='position:absolute; left:1; top:10' href='http://www.webkitgtk.org'&gt;WebKitGTK+ Website&lt;/a&gt;&lt;/body&gt;&lt;/html&gt;&quot;,
+        &quot;ContextMenuTestDefault&quot;);
+    test-&gt;waitUntilLoadFinished();
+
+    // Default context menu.
+    test-&gt;showContextMenuAtPositionAndWaitUntilFinished(1, 1);
+    g_assert_cmpuint(test-&gt;m_actions.size(), ==, 4);
+    g_assert_cmpuint(test-&gt;m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK);
+    g_assert_cmpuint(test-&gt;m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD);
+    g_assert_cmpuint(test-&gt;m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_STOP);
+    g_assert_cmpuint(test-&gt;m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
+
+    // Link menu.
+    test-&gt;showContextMenuAtPositionAndWaitUntilFinished(1, 11);
+    g_assert_cmpuint(test-&gt;m_actions.size(), ==, 4);
+    g_assert_cmpuint(test-&gt;m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK);
+    g_assert_cmpuint(test-&gt;m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW);
+    g_assert_cmpuint(test-&gt;m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK);
+    g_assert_cmpuint(test-&gt;m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD);
+
+    // Custom menu.
+    test-&gt;loadHtml(&quot;&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;&quot;, &quot;ContextMenuTestCustom&quot;);
+    test-&gt;showContextMenuAndWaitUntilFinished();
+    g_assert_cmpuint(test-&gt;m_actions.size(), ==, 4);
+    g_assert_cmpuint(test-&gt;m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_STOP);
+    g_assert_cmpuint(test-&gt;m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
+    g_assert_cmpuint(test-&gt;m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION);
+    g_assert_cmpuint(test-&gt;m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT);
+
+    // Menu cleared by the web process.
+    test-&gt;loadHtml(&quot;&lt;html&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;&quot;, &quot;ContextMenuTestClear&quot;);
+    test-&gt;showContextMenuAndWaitUntilFinished();
+    g_assert_cmpuint(test-&gt;m_actions.size(), ==, 0);
+}
+
+class ContextMenuWebExtensionNodeTest: public ContextMenuTest {
+public:
+    MAKE_GLIB_TEST_FIXTURE(ContextMenuWebExtensionNodeTest);
+
+    struct Node {
+        enum {
+            NodeUnknown = 0,
+            NodeElement = 1,
+            NodeText = 3
+        };
+        typedef unsigned Type;
+
+        CString name;
+        Type type;
+        CString contents;
+        CString parentName;
+    };
+
+    void deserializeNodeFromUserData(GVariant* userData)
+    {
+        GVariantIter iter;
+        g_variant_iter_init(&amp;iter, userData);
+
+        const char* key;
+        GVariant* value;
+        while (g_variant_iter_next(&amp;iter, &quot;{&amp;sv}&quot;, &amp;key, &amp;value)) {
+            if (!strcmp(key, &quot;Name&quot;) &amp;&amp; g_variant_classify(value) == G_VARIANT_CLASS_STRING)
+                m_node.name = g_variant_get_string(value, nullptr);
+            else if (!strcmp(key, &quot;Type&quot;) &amp;&amp; g_variant_classify(value) == G_VARIANT_CLASS_UINT32)
+                m_node.type = g_variant_get_uint32(value);
+            else if (!strcmp(key, &quot;Contents&quot;) &amp;&amp; g_variant_classify(value) == G_VARIANT_CLASS_STRING)
+                m_node.contents = g_variant_get_string(value, nullptr);
+            else if (!strcmp(key, &quot;Parent&quot;) &amp;&amp; g_variant_classify(value) == G_VARIANT_CLASS_STRING)
+                m_node.parentName = g_variant_get_string(value, nullptr);
+            g_variant_unref(value);
+        }
+    }
+
+    bool contextMenu(WebKitContextMenu* menu, GdkEvent*, WebKitHitTestResult*)
+    {
+        deserializeNodeFromUserData(webkit_context_menu_get_user_data(menu));
+        quitMainLoop();
+
+        return true;
+    }
+
+    Node m_node;
+};
+
+static void testContextMenuWebExtensionNode(ContextMenuWebExtensionNodeTest* test, gconstpointer)
+{
+    test-&gt;showInWindowAndWaitUntilMapped();
+    test-&gt;loadHtml(&quot;&lt;html&gt;&lt;body&gt;&lt;p style='position:absolute; left:1; top:1'&gt;WebKitGTK+ Context menu tests&lt;/p&gt;&lt;br&gt;&quot;
+        &quot;&lt;a style='position:absolute; left:1; top:100' href='http://www.webkitgtk.org'&gt;WebKitGTK+ Website&lt;/a&gt;&lt;/body&gt;&lt;/html&gt;&quot;,
+        &quot;ContextMenuTestNode&quot;);
+    test-&gt;waitUntilLoadFinished();
+
+    test-&gt;showContextMenuAtPositionAndWaitUntilFinished(0, 0);
+    g_assert_cmpstr(test-&gt;m_node.name.data(), ==, &quot;HTML&quot;);
+    g_assert_cmpuint(test-&gt;m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeElement);
+    g_assert_cmpstr(test-&gt;m_node.contents.data(), ==, &quot;WebKitGTK+ Context menu testsWebKitGTK+ Website&quot;);
+    g_assert_cmpstr(test-&gt;m_node.parentName.data(), ==, &quot;#document&quot;);
+
+    test-&gt;showContextMenuAtPositionAndWaitUntilFinished(1, 20);
+    g_assert_cmpstr(test-&gt;m_node.name.data(), ==, &quot;#text&quot;);
+    g_assert_cmpuint(test-&gt;m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeText);
+    g_assert_cmpstr(test-&gt;m_node.contents.data(), ==, &quot;WebKitGTK+ Context menu tests&quot;);
+    g_assert_cmpstr(test-&gt;m_node.parentName.data(), ==, &quot;P&quot;);
+
+    // Link menu.
+    test-&gt;showContextMenuAtPositionAndWaitUntilFinished(1, 101);
+    g_assert_cmpstr(test-&gt;m_node.name.data(), ==, &quot;#text&quot;);
+    g_assert_cmpuint(test-&gt;m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeText);
+    g_assert_cmpstr(test-&gt;m_node.contents.data(), ==, &quot;WebKitGTK+ Website&quot;);
+    g_assert_cmpstr(test-&gt;m_node.parentName.data(), ==, &quot;A&quot;);
+}
+
</ins><span class="cx"> void beforeAll()
</span><span class="cx"> {
</span><ins>+    webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
</ins><span class="cx">     ContextMenuDefaultTest::add(&quot;WebKitWebView&quot;, &quot;default-menu&quot;, testContextMenuDefaultMenu);
</span><span class="cx">     ContextMenuCustomTest::add(&quot;WebKitWebView&quot;, &quot;populate-menu&quot;, testContextMenuPopulateMenu);
</span><span class="cx">     ContextMenuCustomFullTest::add(&quot;WebKitWebView&quot;, &quot;custom-menu&quot;, testContextMenuCustomMenu);
</span><span class="lines">@@ -891,6 +1048,8 @@
</span><span class="cx">     ContextMenuSubmenuTest::add(&quot;WebKitWebView&quot;, &quot;submenu&quot;, testContextMenuSubMenu);
</span><span class="cx">     ContextMenuDismissedTest::add(&quot;WebKitWebView&quot;, &quot;menu-dismissed&quot;, testContextMenuDismissed);
</span><span class="cx">     ContextMenuSmartSeparatorsTest::add(&quot;WebKitWebView&quot;, &quot;smart-separators&quot;, testContextMenuSmartSeparators);
</span><ins>+    ContextMenuWebExtensionTest::add(&quot;WebKitWebPage&quot;, &quot;context-menu&quot;, testContextMenuWebExtensionMenu);
+    ContextMenuWebExtensionNodeTest::add(&quot;WebKitWebPage&quot;, &quot;context-menu-node&quot;, testContextMenuWebExtensionNode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void afterAll()
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2GtkWebExtensionTestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp (175693 => 175694)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp        2014-11-06 10:31:53 UTC (rev 175693)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp        2014-11-06 15:08:07 UTC (rev 175694)
</span><span class="lines">@@ -159,11 +159,67 @@
</span><span class="cx">     return FALSE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static GVariant* serializeContextMenu(WebKitContextMenu* menu)
+{
+    GVariantBuilder builder;
+    g_variant_builder_init(&amp;builder, G_VARIANT_TYPE_ARRAY);
+    GList* items = webkit_context_menu_get_items(menu);
+    for (GList* it = items; it; it = g_list_next(it))
+        g_variant_builder_add(&amp;builder, &quot;u&quot;, webkit_context_menu_item_get_stock_action(WEBKIT_CONTEXT_MENU_ITEM(it-&gt;data)));
+    return g_variant_builder_end(&amp;builder);
+}
+
+static GVariant* serializeNode(WebKitDOMNode* node)
+{
+    GVariantBuilder builder;
+    g_variant_builder_init(&amp;builder, G_VARIANT_TYPE_ARRAY);
+    g_variant_builder_add(&amp;builder, &quot;{sv}&quot;, &quot;Name&quot;, g_variant_new_take_string(webkit_dom_node_get_node_name(node)));
+    g_variant_builder_add(&amp;builder, &quot;{sv}&quot;, &quot;Type&quot;, g_variant_new_uint32(webkit_dom_node_get_node_type(node)));
+    g_variant_builder_add(&amp;builder, &quot;{sv}&quot;, &quot;Contents&quot;, g_variant_new_take_string(webkit_dom_node_get_text_content(node)));
+    WebKitDOMNode* parent = webkit_dom_node_get_parent_node(node);
+    g_variant_builder_add(&amp;builder, &quot;{sv}&quot;, &quot;Parent&quot;, parent ? g_variant_new_take_string(webkit_dom_node_get_node_name(parent)) : g_variant_new_string(&quot;ROOT&quot;));
+    return g_variant_builder_end(&amp;builder);
+}
+
+static gboolean contextMenuCallback(WebKitWebPage* page, WebKitContextMenu* menu, WebKitWebHitTestResult* hitTestResult, gpointer)
+{
+    const char* pageURI = webkit_web_page_get_uri(page);
+    if (!g_strcmp0(pageURI, &quot;ContextMenuTestDefault&quot;)) {
+        webkit_context_menu_set_user_data(menu, serializeContextMenu(menu));
+        return FALSE;
+    }
+
+    if (!g_strcmp0(pageURI, &quot;ContextMenuTestCustom&quot;)) {
+        // Remove Back and Forward, and add Inspector action.
+        webkit_context_menu_remove(menu, webkit_context_menu_first(menu));
+        webkit_context_menu_remove(menu, webkit_context_menu_first(menu));
+        webkit_context_menu_append(menu, webkit_context_menu_item_new_separator());
+        webkit_context_menu_append(menu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT));
+        webkit_context_menu_set_user_data(menu, serializeContextMenu(menu));
+        return TRUE;
+    }
+
+    if (!g_strcmp0(pageURI, &quot;ContextMenuTestClear&quot;)) {
+        webkit_context_menu_remove_all(menu);
+        return TRUE;
+    }
+
+    if (!g_strcmp0(pageURI, &quot;ContextMenuTestNode&quot;)) {
+        WebKitDOMNode* node = webkit_web_hit_test_result_get_node(hitTestResult);
+        g_assert(WEBKIT_DOM_IS_NODE(node));
+        webkit_context_menu_set_user_data(menu, serializeNode(node));
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
</ins><span class="cx"> static void pageCreatedCallback(WebKitWebExtension* extension, WebKitWebPage* webPage, gpointer)
</span><span class="cx"> {
</span><span class="cx">     g_signal_connect(webPage, &quot;document-loaded&quot;, G_CALLBACK(documentLoadedCallback), extension);
</span><span class="cx">     g_signal_connect(webPage, &quot;notify::uri&quot;, G_CALLBACK(uriChangedCallback), extension);
</span><del>-    g_signal_connect(webPage, &quot;send-request&quot;, G_CALLBACK(sendRequestCallback), 0);
</del><ins>+    g_signal_connect(webPage, &quot;send-request&quot;, G_CALLBACK(sendRequestCallback), nullptr);
+    g_signal_connect(webPage, &quot;context-menu&quot;, G_CALLBACK(contextMenuCallback), nullptr);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static JSValueRef echoCallback(JSContextRef jsContext, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef*)
</span></span></pre>
</div>
</div>

</body>
</html>