[GTK] Add inspector API to WebKit2 GTK+
https://bugs.webkit.org/show_bug.cgi?id=87113

Reviewed by Martin Robinson.

* GNUmakefile.list.am: Add new files to compilation.
* UIProcess/API/C/gtk/WKInspectorClientGtk.cpp: Added.
(WKInspectorSetInspectorClientGtk):
* UIProcess/API/C/gtk/WKInspectorClientGtk.h: Added.
* UIProcess/API/gtk/WebKitPrivate.h:
* UIProcess/API/gtk/WebKitWebInspector.cpp: Added.
(webkitWebInspectorFinalize):
(webkit_web_inspector_init):
(webkit_web_inspector_class_init):
(openWindow): Emit WebKitWebInspector::open-window singal.
(didClose): Emit WebKitWebInspector::closed signal.
(bringToFront): Emit WebKitWebInspector::bring-to-front singal.
(inspectedURLChanged): Set the inspected URI and emit
GObject::notify signal if it changed.
(attach): Emit WebKitWebInspector::attach signal.
(detach): Emit WebKitWebInspector::detach signal.
(didChangeAttachedHeight): Set the attached height and emit
GObject::notify signal if it changed.
(webkitWebInspectorCreate): Ceate a new WebKitWebInspector object
for the given WKInspector. Also initialize and set the inspector
client.
(webkit_web_inspector_get_web_view): Return the web view used to
render the inspector.
(webkit_web_inspector_get_inspected_uri): Return the URI that is
being inspected.
(webkit_web_inspector_is_attached): Whether the inspector view is
currently attached.
(webkit_web_inspector_attach): Request to attach the inspector.
(webkit_web_inspector_detach): Request to detach the inspector.
(webkit_web_inspector_show): Request to show the inspector.
(webkit_web_inspector_close): Request to close the inspector.
(webkit_web_inspector_get_attached_height): Return the height that
the inspector view should have when attached.
* UIProcess/API/gtk/WebKitWebInspector.h: Added.
* UIProcess/API/gtk/WebKitWebInspectorPrivate.h: Added.
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkit_web_view_get_inspector): Return the WebKitWebInspector
associated to the web view.
* UIProcess/API/gtk/WebKitWebView.h:
* UIProcess/API/gtk/docs/webkit2gtk-docs.sgml: Add new section for
WebKitWebInspector.
* UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Ad new symbols.
* UIProcess/API/gtk/docs/webkit2gtk.types: Add
webkit_web_inspector_get_type.
* UIProcess/API/gtk/tests/GNUmakefile.am: Add new test for the
inspector API.
* UIProcess/API/gtk/tests/TestInspector.cpp: Added.
(testInspectorDefault):
(testInspectorCustom):
(testInspectorWindowDestroyed):
(beforeAll):
(afterAll):
* UIProcess/API/gtk/tests/WebViewTest.cpp:
(WebViewTest::showInWindowAndWaitUntilMapped): Add optional
parameter to create a toplevel or popup window.
(WebViewTest::resizeView): Helper function to set the widget
allocation to a given size.
* UIProcess/API/gtk/tests/WebViewTest.h:
* UIProcess/API/gtk/webkit2.h: Include WebKitWebInspector.h
* UIProcess/WebInspectorProxy.h:
(WebKit::WebInspectorProxy::inspectorView): Return the view used
to render the inspector.
* UIProcess/gtk/WebInspectorClientGtk.cpp: Added.
(WebKit::WebInspectorClientGtk::openWindow):
(WebKit::WebInspectorClientGtk::didClose):
(WebKit::WebInspectorClientGtk::bringToFront):
(WebKit::WebInspectorClientGtk::inspectedURLChanged):
(WebKit::WebInspectorClientGtk::attach):
(WebKit::WebInspectorClientGtk::detach):
(WebKit::WebInspectorClientGtk::didChangeAttachedHeight):
* UIProcess/gtk/WebInspectorClientGtk.h: Added.
* UIProcess/gtk/WebInspectorProxyGtk.cpp:
(WebKit::inspectorViewDestroyed): Close the inspector page when
the inspector view is destroyed, instead of when the inspector
window is deleted, because the inspector view can now be inside a
window created by the user.
(WebKit::WebInspectorProxy::initializeInspectorClientGtk):
Initialze the inspector client.
(WebKit::WebInspectorProxy::platformCreateInspectorPage): Add a
weak pointer to the inspector view to make sure it's NULL when
destroyed.
(WebKit::WebInspectorProxy::createInspectorWindow): Call
openWindow on the inspector client, and return early if the
callback was handled.
(WebKit::WebInspectorProxy::platformOpen): Connect to destroy
signal of the inspector view to close the page when the view is
destroyed.
(WebKit::WebInspectorProxy::platformDidClose): Call didClose on
the inspector client.
(WebKit::WebInspectorProxy::platformBringToFront): Call
bringToFront on the inspector client, and return early if the
callback was handled.
(WebKit::WebInspectorProxy::platformInspectedURLChanged): Call
inspectedURLChanged on the inspector client.
(WebKit::WebInspectorProxy::platformAttach): Call attach on the
inspector client and return if the callback was handled.
(WebKit::WebInspectorProxy::platformDetach): Call detach on the
inspector client and return if the callback was handled.
(WebKit::WebInspectorProxy::platformSetAttachedWindowHeight): Call
didChangeAttachedHeight on the inspector client.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@118146 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebKit2/ChangeLog b/Source/WebKit2/ChangeLog
index e1cd06e..2f46bba 100644
--- a/Source/WebKit2/ChangeLog
+++ b/Source/WebKit2/ChangeLog
@@ -1,3 +1,111 @@
+2012-05-22  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] Add inspector API to WebKit2 GTK+
+        https://bugs.webkit.org/show_bug.cgi?id=87113
+
+        Reviewed by Martin Robinson.
+
+        * GNUmakefile.list.am: Add new files to compilation.
+        * UIProcess/API/C/gtk/WKInspectorClientGtk.cpp: Added.
+        (WKInspectorSetInspectorClientGtk):
+        * UIProcess/API/C/gtk/WKInspectorClientGtk.h: Added.
+        * UIProcess/API/gtk/WebKitPrivate.h:
+        * UIProcess/API/gtk/WebKitWebInspector.cpp: Added.
+        (webkitWebInspectorFinalize):
+        (webkit_web_inspector_init):
+        (webkit_web_inspector_class_init):
+        (openWindow): Emit WebKitWebInspector::open-window singal.
+        (didClose): Emit WebKitWebInspector::closed signal.
+        (bringToFront): Emit WebKitWebInspector::bring-to-front singal.
+        (inspectedURLChanged): Set the inspected URI and emit
+        GObject::notify signal if it changed.
+        (attach): Emit WebKitWebInspector::attach signal.
+        (detach): Emit WebKitWebInspector::detach signal.
+        (didChangeAttachedHeight): Set the attached height and emit
+        GObject::notify signal if it changed.
+        (webkitWebInspectorCreate): Ceate a new WebKitWebInspector object
+        for the given WKInspector. Also initialize and set the inspector
+        client.
+        (webkit_web_inspector_get_web_view): Return the web view used to
+        render the inspector.
+        (webkit_web_inspector_get_inspected_uri): Return the URI that is
+        being inspected.
+        (webkit_web_inspector_is_attached): Whether the inspector view is
+        currently attached.
+        (webkit_web_inspector_attach): Request to attach the inspector.
+        (webkit_web_inspector_detach): Request to detach the inspector.
+        (webkit_web_inspector_show): Request to show the inspector.
+        (webkit_web_inspector_close): Request to close the inspector.
+        (webkit_web_inspector_get_attached_height): Return the height that
+        the inspector view should have when attached.
+        * UIProcess/API/gtk/WebKitWebInspector.h: Added.
+        * UIProcess/API/gtk/WebKitWebInspectorPrivate.h: Added.
+        * UIProcess/API/gtk/WebKitWebView.cpp:
+        (webkit_web_view_get_inspector): Return the WebKitWebInspector
+        associated to the web view.
+        * UIProcess/API/gtk/WebKitWebView.h:
+        * UIProcess/API/gtk/docs/webkit2gtk-docs.sgml: Add new section for
+        WebKitWebInspector.
+        * UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Ad new symbols.
+        * UIProcess/API/gtk/docs/webkit2gtk.types: Add
+        webkit_web_inspector_get_type.
+        * UIProcess/API/gtk/tests/GNUmakefile.am: Add new test for the
+        inspector API.
+        * UIProcess/API/gtk/tests/TestInspector.cpp: Added.
+        (testInspectorDefault):
+        (testInspectorCustom):
+        (testInspectorWindowDestroyed):
+        (beforeAll):
+        (afterAll):
+        * UIProcess/API/gtk/tests/WebViewTest.cpp:
+        (WebViewTest::showInWindowAndWaitUntilMapped): Add optional
+        parameter to create a toplevel or popup window.
+        (WebViewTest::resizeView): Helper function to set the widget
+        allocation to a given size.
+        * UIProcess/API/gtk/tests/WebViewTest.h:
+        * UIProcess/API/gtk/webkit2.h: Include WebKitWebInspector.h
+        * UIProcess/WebInspectorProxy.h:
+        (WebKit::WebInspectorProxy::inspectorView): Return the view used
+        to render the inspector.
+        * UIProcess/gtk/WebInspectorClientGtk.cpp: Added.
+        (WebKit::WebInspectorClientGtk::openWindow):
+        (WebKit::WebInspectorClientGtk::didClose):
+        (WebKit::WebInspectorClientGtk::bringToFront):
+        (WebKit::WebInspectorClientGtk::inspectedURLChanged):
+        (WebKit::WebInspectorClientGtk::attach):
+        (WebKit::WebInspectorClientGtk::detach):
+        (WebKit::WebInspectorClientGtk::didChangeAttachedHeight):
+        * UIProcess/gtk/WebInspectorClientGtk.h: Added.
+        * UIProcess/gtk/WebInspectorProxyGtk.cpp:
+        (WebKit::inspectorViewDestroyed): Close the inspector page when
+        the inspector view is destroyed, instead of when the inspector
+        window is deleted, because the inspector view can now be inside a
+        window created by the user.
+        (WebKit::WebInspectorProxy::initializeInspectorClientGtk):
+        Initialze the inspector client.
+        (WebKit::WebInspectorProxy::platformCreateInspectorPage): Add a
+        weak pointer to the inspector view to make sure it's NULL when
+        destroyed.
+        (WebKit::WebInspectorProxy::createInspectorWindow): Call
+        openWindow on the inspector client, and return early if the
+        callback was handled.
+        (WebKit::WebInspectorProxy::platformOpen): Connect to destroy
+        signal of the inspector view to close the page when the view is
+        destroyed.
+        (WebKit::WebInspectorProxy::platformDidClose): Call didClose on
+        the inspector client.
+        (WebKit::WebInspectorProxy::platformBringToFront): Call
+        bringToFront on the inspector client, and return early if the
+        callback was handled.
+        (WebKit::WebInspectorProxy::platformInspectedURLChanged): Call
+        inspectedURLChanged on the inspector client.
+        (WebKit::WebInspectorProxy::platformAttach): Call attach on the
+        inspector client and return if the callback was handled.
+        (WebKit::WebInspectorProxy::platformDetach): Call detach on the
+        inspector client and return if the callback was handled.
+        (WebKit::WebInspectorProxy::platformSetAttachedWindowHeight): Call
+        didChangeAttachedHeight on the inspector client.
+
 2012-05-22  Anders Carlsson  <andersca@apple.com>
 
         Functions dispatched by dispatchAfterEnsuringUpdatedScrollPosition can be called after drawing area has been destroyed
diff --git a/Source/WebKit2/GNUmakefile.list.am b/Source/WebKit2/GNUmakefile.list.am
index b0db5a2..a19d4a0 100644
--- a/Source/WebKit2/GNUmakefile.list.am
+++ b/Source/WebKit2/GNUmakefile.list.am
@@ -35,6 +35,7 @@
 	$(WebKit2)/Shared/API/c/WKUserContentURLPattern.h \
 	$(WebKit2)/UIProcess/API/C/gtk/WKAPICastGtk.h \
 	$(WebKit2)/UIProcess/API/C/gtk/WKFullScreenClientGtk.h \
+	$(WebKit2)/UIProcess/API/C/gtk/WKInspectorClientGtk.h \
 	$(WebKit2)/UIProcess/API/C/gtk/WKView.h \
 	$(WebKit2)/UIProcess/API/C/soup/WKAPICastSoup.h \
 	$(WebKit2)/UIProcess/API/C/soup/WKContextSoup.h \
@@ -469,6 +470,8 @@
 	Source/WebKit2/UIProcess/API/C/gtk/WKAPICastGtk.h \
 	Source/WebKit2/UIProcess/API/C/gtk/WKFullScreenClientGtk.cpp \
 	Source/WebKit2/UIProcess/API/C/gtk/WKFullScreenClientGtk.h \
+	Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.cpp \
+	Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.h \
 	Source/WebKit2/UIProcess/API/C/gtk/WKView.cpp \
 	Source/WebKit2/UIProcess/API/C/gtk/WKView.h \
 	Source/WebKit2/UIProcess/API/C/soup/WKAPICastSoup.h \
@@ -628,6 +631,9 @@
 	Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.h \
 	Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp \
 	Source/WebKit2/UIProcess/API/gtk/WebKitWebContextPrivate.h \
+	Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.cpp \
+	Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.h \
+	Source/WebKit2/UIProcess/API/gtk/WebKitWebInspectorPrivate.h \
 	Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp \
 	Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.h \
 	Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h \
@@ -675,6 +681,8 @@
 	Source/WebKit2/UIProcess/gtk/WebFullScreenClientGtk.cpp \
 	Source/WebKit2/UIProcess/gtk/WebFullScreenClientGtk.h \
 	Source/WebKit2/UIProcess/gtk/WebFullScreenManagerProxyGtk.cpp \
+	Source/WebKit2/UIProcess/gtk/WebInspectorClientGtk.cpp \
+	Source/WebKit2/UIProcess/gtk/WebInspectorClientGtk.h \
 	Source/WebKit2/UIProcess/gtk/WebInspectorProxyGtk.cpp \
 	Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp \
 	Source/WebKit2/UIProcess/gtk/WebPopupMenuProxyGtk.cpp \
diff --git a/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.cpp b/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.cpp
new file mode 100644
index 0000000..c9d777c
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WKInspectorClientGtk.h"
+
+#include "WKAPICast.h"
+#include "WebInspectorProxy.h"
+
+using namespace WebKit;
+
+void WKInspectorSetInspectorClientGtk(WKInspectorRef inspectorRef, const WKInspectorClientGtk* wkClient)
+{
+    toImpl(inspectorRef)->initializeInspectorClientGtk(wkClient);
+}
diff --git a/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.h b/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.h
new file mode 100644
index 0000000..865e19a
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/C/gtk/WKInspectorClientGtk.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WKInspectorClientGtk_h
+#define WKInspectorClientGtk_h
+
+#include <WebKit2/WKBase.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef bool (*WKInspectorClientGtkInspectorCallback)(WKInspectorRef inspector, const void* clientInfo);
+typedef void (*WKInspectorClientGtkInspectorDidCloseCallback)(WKInspectorRef inspector, const void* clientInfo);
+typedef void (*WKInspectorClientGtkInspectedURLChangedCallback)(WKInspectorRef inspector, WKStringRef url, const void* clientInfo);
+typedef void (*WKInspectorClientGtkDidChangeAttachedHeightCallback)(WKInspectorRef inspector, unsigned height, const void* clientInfo);
+
+struct WKInspectorClientGtk {
+    int                                                 version;
+    const void*                                         clientInfo;
+    WKInspectorClientGtkInspectorCallback               openWindow;
+    WKInspectorClientGtkInspectorDidCloseCallback       didClose;
+    WKInspectorClientGtkInspectorCallback               bringToFront;
+    WKInspectorClientGtkInspectedURLChangedCallback     inspectedURLChanged;
+    WKInspectorClientGtkInspectorCallback               attach;
+    WKInspectorClientGtkInspectorCallback               detach;
+    WKInspectorClientGtkDidChangeAttachedHeightCallback didChangeAttachedHeight;
+};
+typedef struct WKInspectorClientGtk WKInspectorClientGtk;
+
+enum { kWKInspectorClientGtkCurrentVersion = 0 };
+
+WK_EXPORT void WKInspectorSetInspectorClientGtk(WKInspectorRef inspectorRef, const WKInspectorClientGtk* client);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WKInspectorClientGtk_h */
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h
index 7df7b67..b7c5370 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitPrivate.h
@@ -30,6 +30,8 @@
 #include <WebKit2/WKDownload.h>
 #include <WebKit2/WKFindOptions.h>
 #include <WebKit2/WKFullScreenClientGtk.h>
+#include <WebKit2/WKInspector.h>
+#include <WebKit2/WKInspectorClientGtk.h>
 #include <WebKit2/WKRetainPtr.h>
 #include <WebKit2/WKSerializedScriptValue.h>
 #include <WebKit2/WKString.h>
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.cpp
new file mode 100644
index 0000000..25023cf
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.cpp
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2012 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 "config.h"
+#include "WebKitWebInspector.h"
+
+#include "WebInspectorProxy.h"
+#include "WebKitMarshal.h"
+#include "WebKitWebInspectorPrivate.h"
+#include <glib/gi18n-lib.h>
+#include <wtf/gobject/GRefPtr.h>
+#include <wtf/text/CString.h>
+
+using namespace WebKit;
+
+enum {
+    OPEN_WINDOW,
+    BRING_TO_FRONT,
+    CLOSED,
+    ATTACH,
+    DETACH,
+
+    LAST_SIGNAL
+};
+
+enum {
+    PROP_0,
+
+    PROP_INSPECTED_URI,
+    PROP_ATTACHED_HEIGHT
+};
+
+struct _WebKitWebInspectorPrivate {
+    WKRetainPtr<WKInspectorRef> wkInspector;
+    CString inspectedURI;
+    unsigned attachedHeight;
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE(WebKitWebInspector, webkit_web_inspector, G_TYPE_OBJECT)
+
+static void webkitWebInspectorGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
+{
+    WebKitWebInspector* inspector = WEBKIT_WEB_INSPECTOR(object);
+
+    switch (propId) {
+    case PROP_INSPECTED_URI:
+        g_value_set_string(value, webkit_web_inspector_get_inspected_uri(inspector));
+        break;
+    case PROP_ATTACHED_HEIGHT:
+        g_value_set_uint(value, webkit_web_inspector_get_attached_height(inspector));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
+    }
+}
+
+static void webkitWebInspectorFinalize(GObject* object)
+{
+    WebKitWebInspectorPrivate* priv = WEBKIT_WEB_INSPECTOR(object)->priv;
+    WKInspectorSetInspectorClientGtk(priv->wkInspector.get(), 0);
+    priv->~WebKitWebInspectorPrivate();
+    G_OBJECT_CLASS(webkit_web_inspector_parent_class)->finalize(object);
+}
+
+static void webkit_web_inspector_init(WebKitWebInspector* inspector)
+{
+    WebKitWebInspectorPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(inspector, WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspectorPrivate);
+    inspector->priv = priv;
+    new (priv) WebKitWebInspectorPrivate();
+}
+
+static void webkit_web_inspector_class_init(WebKitWebInspectorClass* findClass)
+{
+    GObjectClass* gObjectClass = G_OBJECT_CLASS(findClass);
+    gObjectClass->finalize = webkitWebInspectorFinalize;
+    gObjectClass->get_property = webkitWebInspectorGetProperty;
+
+    g_type_class_add_private(findClass, sizeof(WebKitWebInspectorPrivate));
+
+    /**
+     * WebKitWebInspector:inspected-uri:
+     *
+     * The URI that is currently being inspected.
+     */
+    g_object_class_install_property(gObjectClass,
+                                    PROP_INSPECTED_URI,
+                                    g_param_spec_string("inspected-uri",
+                                                        _("Inspected URI"),
+                                                        _("The URI that is currently being inspected"),
+                                                        0,
+                                                        WEBKIT_PARAM_READABLE));
+    /**
+     * WebKitWebInspector:attached-height:
+     *
+     * The height that the inspector view should have when it is attached.
+     */
+    g_object_class_install_property(gObjectClass,
+                                    PROP_ATTACHED_HEIGHT,
+                                    g_param_spec_uint("attached-height",
+                                                      _("Attached Height"),
+                                                      _("The height that the inspector view should have when it is attached"),
+                                                      0, G_MAXUINT, 0,
+                                                      WEBKIT_PARAM_READABLE));
+
+    /**
+     * WebKitWebInspector::open-window:
+     * @inspector: the #WebKitWebInspector on which the signal is emitted
+     *
+     * Emitted when the inspector is requested to open in a separate window.
+     * If this signal is not handled, a #GtkWindow with the inspector will be
+     * created and shown, so you only need to handle this signal if you want
+     * to use your own window.
+     * This signal is emitted after #WebKitWebInspector::detach to show
+     * the inspector in a separate window after being detached.
+     *
+     * To prevent the inspector from being shown you can connect to this
+     * signal and simply return %TRUE
+     *
+     * Returns: %TRUE to stop other handlers from being invoked for the event.
+     *    %FALSE to propagate the event further.
+     */
+    signals[OPEN_WINDOW] =
+        g_signal_new("open-window",
+                     G_TYPE_FROM_CLASS(gObjectClass),
+                     G_SIGNAL_RUN_LAST,
+                     0,
+                     g_signal_accumulator_true_handled, 0,
+                     webkit_marshal_BOOLEAN__VOID,
+                     G_TYPE_BOOLEAN, 0);
+
+    /**
+     * WebKitWebInspector::bring-to-front:
+     * @inspector: the #WebKitWebInspector on which the signal is emitted
+     *
+     * Emitted when the inspector should be shown.
+     *
+     * If the inspector is not attached the inspector window should be shown
+     * on top of any other windows.
+     * If the inspector is attached the inspector view should be made visible.
+     * For example, if the inspector view is attached using a tab in a browser
+     * window, the browser window should be raised and the tab containing the
+     * inspector view should be the active one.
+     * In both cases, if this signal is not handled, the default implementation
+     * calls gtk_window_present() on the current toplevel #GtkWindow of the
+     * inspector view.
+     *
+     * Returns: %TRUE to stop other handlers from being invoked for the event.
+     *    %FALSE to propagate the event further.
+     */
+    signals[BRING_TO_FRONT] =
+        g_signal_new("bring-to-front",
+                     G_TYPE_FROM_CLASS(gObjectClass),
+                     G_SIGNAL_RUN_LAST,
+                     0,
+                     g_signal_accumulator_true_handled, 0,
+                     webkit_marshal_BOOLEAN__VOID,
+                     G_TYPE_BOOLEAN, 0);
+
+    /**
+     * WebKitWebInspector::closed:
+     * @inspector: the #WebKitWebInspector on which the signal is emitted
+     *
+     * Emitted when the inspector page is closed. If you are using your own
+     * inspector window, you should connect to this signal and destroy your
+     * window.
+     */
+    signals[CLOSED] =
+        g_signal_new("closed",
+                     G_TYPE_FROM_CLASS(gObjectClass),
+                     G_SIGNAL_RUN_LAST,
+                     0, 0, 0,
+                     g_cclosure_marshal_VOID__VOID,
+                     G_TYPE_NONE, 0);
+
+    /**
+     * WebKitWebInspector::attach:
+     * @inspector: the #WebKitWebInspector on which the signal is emitted
+     *
+     * Emitted when the inspector is requested to be attached to the window
+     * where the inspected web view is.
+     * If this signal is not handled the inspector view will be automatically
+     * attached to the inspected view, so you only need to handle this signal
+     * if you want to attach the inspector view yourself (for example, to add
+     * the inspector view to a browser tab).
+     *
+     * To prevent the inspector vew from being attached you can connect to this
+     * signal and simply return %TRUE.
+     *
+     * Returns: %TRUE to stop other handlers from being invoked for the event.
+     *    %FALSE to propagate the event further.
+     */
+    signals[ATTACH] =
+        g_signal_new("attach",
+                     G_TYPE_FROM_CLASS(gObjectClass),
+                     G_SIGNAL_RUN_LAST,
+                     0,
+                     g_signal_accumulator_true_handled, 0,
+                     webkit_marshal_BOOLEAN__VOID,
+                     G_TYPE_BOOLEAN, 0);
+
+    /**
+     * WebKitWebInspector::detach:
+     * @inspector: the #WebKitWebInspector on which the signal is emitted
+     *
+     * Emitted when the inspector is requested to be detached from the window
+     * it is currently attached to. The inspector is detached when the inspector page
+     * is about to be closed, and this signal is emitted right before
+     * #WebKitWebInspector::closed, or when the user clicks on the detach button
+     * in the inspector view to show the inspector in a separate window. In this case
+     * the signal #WebKitWebInspector::open-window is emitted after this one.
+     *
+     * To prevent the inspector vew from being detached you can connect to this
+     * signal and simply return %TRUE.
+     *
+     * Returns: %TRUE to stop other handlers from being invoked for the event.
+     *    %FALSE to propagate the event further.
+     */
+    signals[DETACH] =
+        g_signal_new("detach",
+                     G_TYPE_FROM_CLASS(gObjectClass),
+                     G_SIGNAL_RUN_LAST,
+                     0,
+                     g_signal_accumulator_true_handled, 0,
+                     webkit_marshal_BOOLEAN__VOID,
+                     G_TYPE_BOOLEAN, 0);
+}
+
+static bool openWindow(WKInspectorRef, const void* clientInfo)
+{
+    gboolean returnValue;
+    g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[OPEN_WINDOW], 0, &returnValue);
+    return returnValue;
+}
+
+static void didClose(WKInspectorRef, const void* clientInfo)
+{
+    g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[CLOSED], 0);
+}
+
+static bool bringToFront(WKInspectorRef, const void* clientInfo)
+{
+    gboolean returnValue;
+    g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[BRING_TO_FRONT], 0, &returnValue);
+    return returnValue;
+}
+
+static void inspectedURLChanged(WKInspectorRef, WKStringRef url, const void* clientInfo)
+{
+    WebKitWebInspector* inspector = WEBKIT_WEB_INSPECTOR(clientInfo);
+    CString uri = toImpl(url)->string().utf8();
+    if (uri == inspector->priv->inspectedURI)
+        return;
+    inspector->priv->inspectedURI = uri;
+    g_object_notify(G_OBJECT(inspector), "inspected-uri");
+}
+
+static bool attach(WKInspectorRef, const void* clientInfo)
+{
+    gboolean returnValue;
+    g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[ATTACH], 0, &returnValue);
+    return returnValue;
+}
+
+static bool detach(WKInspectorRef inspector, const void* clientInfo)
+{
+    gboolean returnValue;
+    g_signal_emit(WEBKIT_WEB_INSPECTOR(clientInfo), signals[DETACH], 0, &returnValue);
+    return returnValue;
+}
+
+static void didChangeAttachedHeight(WKInspectorRef, unsigned height, const void* clientInfo)
+{
+    WebKitWebInspector* inspector = WEBKIT_WEB_INSPECTOR(clientInfo);
+    if (inspector->priv->attachedHeight == height)
+        return;
+    inspector->priv->attachedHeight = height;
+    g_object_notify(G_OBJECT(inspector), "attached-height");
+}
+
+WebKitWebInspector* webkitWebInspectorCreate(WKInspectorRef wkInspector)
+{
+    WebKitWebInspector* inspector = WEBKIT_WEB_INSPECTOR(g_object_new(WEBKIT_TYPE_WEB_INSPECTOR, NULL));
+    inspector->priv->wkInspector = wkInspector;
+
+    WKInspectorClientGtk wkInspectorClientGtk = {
+        kWKInspectorClientGtkCurrentVersion,
+        inspector, // clientInfo
+        openWindow,
+        didClose,
+        bringToFront,
+        inspectedURLChanged,
+        attach,
+        detach,
+        didChangeAttachedHeight
+    };
+    WKInspectorSetInspectorClientGtk(wkInspector, &wkInspectorClientGtk);
+
+    return inspector;
+}
+
+/**
+ * webkit_web_inspector_get_web_view:
+ * @inspector: a #WebKitWebInspector
+ *
+ * Get the #WebKitWebViewBase used to display the inspector.
+ * This might be %NULL if the inspector hasn't been loaded yet,
+ * or it has been closed.
+ *
+ * Returns: (transfer none): the #WebKitWebViewBase used to display the inspector or %NULL
+ */
+WebKitWebViewBase* webkit_web_inspector_get_web_view(WebKitWebInspector* inspector)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector), 0);
+
+    return WEBKIT_WEB_VIEW_BASE(toImpl(inspector->priv->wkInspector.get())->inspectorView());
+}
+
+/**
+ * webkit_web_inspector_get_inspected_uri:
+ * @inspector: a #WebKitWebInspector
+ *
+ * Get the URI that is currently being inspected. This can be %NULL if
+ * nothing has been loaded yet in the inspected view, if the inspector
+ * has been closed or when inspected view was loaded from a HTML string
+ * instead of a URI.
+ *
+ * Returns: the URI that is currently being inspected or %NULL
+ */
+const char* webkit_web_inspector_get_inspected_uri(WebKitWebInspector* inspector)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector), 0);
+
+    return inspector->priv->inspectedURI.data();
+}
+
+/**
+ * webkit_web_inspector_is_attached:
+ * @inspector: a #WebKitWebInspector
+ *
+ * Whether the @inspector view is currently attached to the same window that contains
+ * the inspected view.
+ *
+ * Returns: %TRUE if @inspector is currently attached or %FALSE otherwise
+ */
+gboolean webkit_web_inspector_is_attached(WebKitWebInspector* inspector)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector), FALSE);
+
+    return WKInspectorIsAttached(inspector->priv->wkInspector.get());
+}
+
+/**
+ * webkit_web_inspector_attach:
+ * @inspector: a #WebKitWebInspector
+ *
+ * Request @inspector to be attached. The signal #WebKitWebInspector::attach
+ * will be emitted. If the inspector is already attached it does nothing.
+ */
+void webkit_web_inspector_attach(WebKitWebInspector* inspector)
+{
+    g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector));
+
+    if (WKInspectorIsAttached(inspector->priv->wkInspector.get()))
+        return;
+    WKInspectorAttach(inspector->priv->wkInspector.get());
+}
+
+/**
+ * webkit_web_inspector_detach:
+ * @inspector: a #WebKitWebInspector
+ *
+ * Request @inspector to be detached. The signal #WebKitWebInspector::detach
+ * will be emitted. If the inspector is already detached it does nothing.
+ */
+void webkit_web_inspector_detach(WebKitWebInspector* inspector)
+{
+    g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector));
+
+    if (!WKInspectorIsAttached(inspector->priv->wkInspector.get()))
+        return;
+    WKInspectorDetach(inspector->priv->wkInspector.get());
+}
+
+/**
+ * webkit_web_inspector_show:
+ * @inspector: a #WebKitWebInspector
+ *
+ * Request @inspector to be shown.
+ */
+void webkit_web_inspector_show(WebKitWebInspector* inspector)
+{
+    g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector));
+
+    WKInspectorShow(inspector->priv->wkInspector.get());
+}
+
+/**
+ * webkit_web_inspector_close:
+ * @inspector: a #WebKitWebInspector
+ *
+ * Request @inspector to be closed.
+ */
+void webkit_web_inspector_close(WebKitWebInspector* inspector)
+{
+    g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector));
+
+    WKInspectorClose(inspector->priv->wkInspector.get());
+}
+
+/**
+ * webkit_web_inspector_get_attached_height:
+ * @inspector: a #WebKitWebInspector
+ *
+ * Get the height that the inspector view should have when
+ * it's attached. If the inspector view is not attached this
+ * returns 0.
+ *
+ * Returns: the height of the inspector view when attached
+ */
+guint webkit_web_inspector_get_attached_height(WebKitWebInspector* inspector)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_INSPECTOR(inspector), 0);
+
+    if (!WKInspectorIsAttached(inspector->priv->wkInspector.get()))
+        return 0;
+    return inspector->priv->attachedHeight;
+}
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.h
new file mode 100644
index 0000000..10c2810
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspector.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 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(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION)
+#error "Only <webkit2/webkit2.h> can be included directly."
+#endif
+
+#ifndef WebKitWebInspector_h
+#define WebKitWebInspector_h
+
+#include <glib-object.h>
+#include <webkit2/WebKitDefines.h>
+#include <webkit2/WebKitWebViewBase.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_WEB_INSPECTOR            (webkit_web_inspector_get_type())
+#define WEBKIT_WEB_INSPECTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspector))
+#define WEBKIT_IS_WEB_INSPECTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_WEB_INSPECTOR))
+#define WEBKIT_WEB_INSPECTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspectorClass))
+#define WEBKIT_IS_WEB_INSPECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  WEBKIT_TYPE_WEB_INSPECTOR))
+#define WEBKIT_WEB_INSPECTOR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspectorClass))
+
+typedef struct _WebKitWebInspector        WebKitWebInspector;
+typedef struct _WebKitWebInspectorClass   WebKitWebInspectorClass;
+typedef struct _WebKitWebInspectorPrivate WebKitWebInspectorPrivate;
+
+struct _WebKitWebInspector {
+    GObject parent;
+
+    WebKitWebInspectorPrivate *priv;
+};
+
+struct _WebKitWebInspectorClass {
+    GObjectClass parent_class;
+};
+
+WEBKIT_API GType
+webkit_web_inspector_get_type            (void);
+
+WEBKIT_API WebKitWebViewBase *
+webkit_web_inspector_get_web_view        (WebKitWebInspector *inspector);
+
+WEBKIT_API const char *
+webkit_web_inspector_get_inspected_uri   (WebKitWebInspector *inspector);
+
+WEBKIT_API gboolean
+webkit_web_inspector_is_attached         (WebKitWebInspector *inspector);
+
+WEBKIT_API void
+webkit_web_inspector_attach              (WebKitWebInspector *inspector);
+
+WEBKIT_API void
+webkit_web_inspector_detach              (WebKitWebInspector *inspector);
+
+WEBKIT_API void
+webkit_web_inspector_show                (WebKitWebInspector *inspector);
+
+WEBKIT_API void
+webkit_web_inspector_close               (WebKitWebInspector *inspector);
+
+WEBKIT_API guint
+webkit_web_inspector_get_attached_height (WebKitWebInspector *inspector);
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspectorPrivate.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspectorPrivate.h
new file mode 100644
index 0000000..7034721
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebInspectorPrivate.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 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 WebKitWebInspectorPrivate_h
+#define WebKitWebInspectorPrivate_h
+
+#include "WebKitPrivate.h"
+#include "WebKitWebInspector.h"
+
+WebKitWebInspector* webkitWebInspectorCreate(WKInspectorRef);
+
+#endif // WebKitWebInspectorPrivate_h
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
index abee3de..65dab6e 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
@@ -37,6 +37,7 @@
 #include "WebKitSettingsPrivate.h"
 #include "WebKitUIClient.h"
 #include "WebKitWebContextPrivate.h"
+#include "WebKitWebInspectorPrivate.h"
 #include "WebKitWebResourcePrivate.h"
 #include "WebKitWebViewBasePrivate.h"
 #include "WebKitWebViewPrivate.h"
@@ -120,6 +121,8 @@
     GRefPtr<WebKitWebResource> mainResource;
     LoadingResourcesMap loadingResourcesMap;
     ResourcesMap subresourcesMap;
+
+    GRefPtr<WebKitWebInspector> inspector;
 };
 
 static guint signals[LAST_SIGNAL] = { 0, };
@@ -1922,3 +1925,23 @@
 
     return g_list_reverse(subresources);
 }
+
+/**
+ * webkit_web_view_get_inspector:
+ * @web_view: a #WebKitWebView
+ *
+ * Get the #WebKitWebInspector associated to @web_view
+ *
+ * Returns: (transfer none): the #WebKitWebInspector of @web_view
+ */
+WebKitWebInspector* webkit_web_view_get_inspector(WebKitWebView* webView)
+{
+    g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
+
+    if (!webView->priv->inspector) {
+        WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
+        webView->priv->inspector = adoptGRef(webkitWebInspectorCreate(toAPI(page->inspector())));
+    }
+
+    return webView->priv->inspector.get();
+}
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h
index 92265b2..4f5fe18 100644
--- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h
+++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h
@@ -40,6 +40,7 @@
 #include <webkit2/WebKitSettings.h>
 #include <webkit2/WebKitURIRequest.h>
 #include <webkit2/WebKitWebContext.h>
+#include <webkit2/WebKitWebInspector.h>
 #include <webkit2/WebKitWebResource.h>
 #include <webkit2/WebKitWebViewBase.h>
 #include <webkit2/WebKitWindowProperties.h>
@@ -298,6 +299,10 @@
 
 WEBKIT_API GList *
 webkit_web_view_get_subresources                   (WebKitWebView             *web_view);
+
+WEBKIT_API WebKitWebInspector *
+webkit_web_view_get_inspector                      (WebKitWebView             *web_view);
+
 G_END_DECLS
 
 #endif
diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml
index 63db05f..b6b9aa0 100644
--- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml
+++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-docs.sgml
@@ -32,6 +32,7 @@
     <xi:include href="xml/WebKitFindController.xml"/>
     <xi:include href="xml/WebKitCookieManager.xml"/>
     <xi:include href="xml/WebKitPlugin.xml"/>
+    <xi:include href="xml/WebKitWebInspector.xml"/>
   </chapter>
 
   <index id="index-all">
diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt
index 884177b..865b5dd 100644
--- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt
+++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-sections.txt
@@ -91,6 +91,7 @@
 webkit_web_view_can_execute_editing_command_finish
 webkit_web_view_execute_editing_command
 webkit_web_view_get_find_controller
+webkit_web_view_get_inspector
 webkit_web_view_get_javascript_global_context
 webkit_web_view_run_javascript
 webkit_web_view_run_javascript_finish
@@ -636,3 +637,29 @@
 webkit_mime_info_get_type
 WebKitPluginPrivate
 </SECTION>
+
+<SECTION>
+<FILE>WebKitWebInspector</FILE>
+WebKitWebInspector
+webkit_web_inspector_get_web_view
+webkit_web_inspector_get_inspected_uri
+webkit_web_inspector_is_attached
+webkit_web_inspector_attach
+webkit_web_inspector_detach
+webkit_web_inspector_show
+webkit_web_inspector_close
+webkit_web_inspector_get_attached_height
+
+<SUBSECTION Standard>
+WebKitWebInspectorClass
+WEBKIT_TYPE_WEB_INSPECTOR
+WEBKIT_WEB_INSPECTOR
+WEBKIT_IS_WEB_INSPECTOR
+WEBKIT_WEB_INSPECTOR_CLASS
+WEBKIT_IS_WEB_INSPECTOR_CLASS
+WEBKIT_WEB_INSPECTOR_GET_CLASS
+
+<SUBSECTION Private>
+webkit_web_inspector_get_type
+WebKitWebInspectorPrivate
+</SECTION>
diff --git a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types
index cdf9edd..92b6fb4 100644
--- a/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types
+++ b/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk.types
@@ -17,3 +17,4 @@
 webkit_cookie_manager_get_type
 webkit_plugin_get_type
 webkit_mime_info_get_type
+webkit_web_inspector_get_type
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am
index 870d68a..8fa0cd8 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/GNUmakefile.am
@@ -4,6 +4,7 @@
 	Programs/WebKit2APITests/TestBackForwardList \
 	Programs/WebKit2APITests/TestCookieManager \
 	Programs/WebKit2APITests/TestDownloads \
+	Programs/WebKit2APITests/TestInspector \
 	Programs/WebKit2APITests/TestLoaderClient \
 	Programs/WebKit2APITests/TestPrinting \
 	Programs/WebKit2APITests/TestResources \
@@ -151,4 +152,12 @@
 Programs_WebKit2APITests_TestCookieManager_LDADD = $(webkit2_tests_ldadd)
 Programs_WebKit2APITests_TestCookieManager_LDFLAGS = $(webkit2_tests_ldflags)
 
+Programs_WebKit2APITests_TestInspector_SOURCES = \
+        Source/WebKit2/UIProcess/API/gtk/tests/TestInspector.cpp
+Programs_WebKit2APITests_TestInspector_CPPFLAGS = \
+	-DWEBKIT_INSPECTOR_PATH=\"${shell pwd}/${top_builddir}/resources/inspector\" \
+	$(webkit2_tests_cppflags)
+Programs_WebKit2APITests_TestInspector_LDADD = $(webkit2_tests_ldadd)
+Programs_WebKit2APITests_TestInspector_LDFLAGS = $(webkit2_tests_ldflags)
+
 endif # ENABLE_WEBKIT2
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/TestInspector.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/TestInspector.cpp
new file mode 100644
index 0000000..9b023f3
--- /dev/null
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/TestInspector.cpp
@@ -0,0 +1,357 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include "config.h"
+
+#include "WebViewTest.h"
+#include <wtf/gobject/GRefPtr.h>
+
+static const unsigned gMinimumAttachedInspectorHeight = 250;
+
+class InspectorTest: public WebViewTest {
+public:
+    MAKE_GLIB_TEST_FIXTURE(InspectorTest);
+
+    enum InspectorEvents {
+        OpenWindow,
+        BringToFront,
+        Closed,
+        Attach,
+        Detach
+    };
+
+    static gboolean openWindowCallback(WebKitWebInspector*, InspectorTest* test)
+    {
+        return test->openWindow();
+    }
+
+    static gboolean bringToFrontCallback(WebKitWebInspector*, InspectorTest* test)
+    {
+        return test->bringToFront();
+    }
+
+    static void closedCallback(WebKitWebInspector*, InspectorTest* test)
+    {
+        return test->closed();
+    }
+
+    static gboolean attachCallback(WebKitWebInspector*, InspectorTest* test)
+    {
+        return test->attach();
+    }
+
+    static gboolean detachCallback(WebKitWebInspector*, InspectorTest* test)
+    {
+        return test->detach();
+    }
+
+    static const unsigned gMinimumAttachedInspectorHeight = 250;
+
+    InspectorTest()
+        : WebViewTest()
+        , m_inspector(webkit_web_view_get_inspector(m_webView))
+        , m_quitOnBringToFront(false)
+    {
+        webkit_settings_set_enable_developer_extras(webkit_web_view_get_settings(m_webView), TRUE);
+        assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_inspector));
+        g_signal_connect(m_inspector, "open-window", G_CALLBACK(openWindowCallback), this);
+        g_signal_connect(m_inspector, "bring-to-front", G_CALLBACK(bringToFrontCallback), this);
+        g_signal_connect(m_inspector, "closed", G_CALLBACK(closedCallback), this);
+        g_signal_connect(m_inspector, "attach", G_CALLBACK(attachCallback), this);
+        g_signal_connect(m_inspector, "detach", G_CALLBACK(detachCallback), this);
+    }
+
+    ~InspectorTest()
+    {
+        g_signal_handlers_disconnect_matched(m_inspector, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+    }
+
+    virtual bool openWindow()
+    {
+        m_events.append(OpenWindow);
+        g_main_loop_quit(m_mainLoop);
+        return TRUE;
+    }
+
+    virtual bool bringToFront()
+    {
+        m_events.append(BringToFront);
+        if (m_quitOnBringToFront)
+            g_main_loop_quit(m_mainLoop);
+        return FALSE;
+    }
+
+    virtual void closed()
+    {
+        m_events.append(Closed);
+        g_main_loop_quit(m_mainLoop);
+    }
+
+    virtual bool attach()
+    {
+        m_events.append(Attach);
+        return TRUE;
+    }
+
+    virtual bool detach()
+    {
+        m_events.append(Detach);
+        return TRUE;
+    }
+
+    void showAndWaitUntilFinished(bool quitOnBringToFront)
+    {
+        m_quitOnBringToFront = quitOnBringToFront;
+        webkit_web_inspector_show(m_inspector);
+        g_main_loop_run(m_mainLoop);
+        m_quitOnBringToFront = false;
+    }
+
+    void resizeViewAndAttach()
+    {
+        // Resize the view to make room for the inspector.
+        resizeView(300, (gMinimumAttachedInspectorHeight + 1) * 4 / 3);
+        webkit_web_inspector_attach(m_inspector);
+    }
+
+    static gboolean detachIdle(InspectorTest* test)
+    {
+        webkit_web_inspector_detach(test->m_inspector);
+        return FALSE;
+    }
+
+    void detachAndWaitUntilWindowOpened()
+    {
+        g_idle_add(reinterpret_cast<GSourceFunc>(detachIdle), this);
+        g_main_loop_run(m_mainLoop);
+    }
+
+    void closeAndWaitUntilClosed()
+    {
+        webkit_web_inspector_close(m_inspector);
+        g_main_loop_run(m_mainLoop);
+    }
+
+    WebKitWebInspector* m_inspector;
+    bool m_quitOnBringToFront;
+    Vector<InspectorEvents> m_events;
+};
+
+static void testInspectorDefault(InspectorTest* test, gconstpointer)
+{
+    test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
+    test->resizeView(200, 200);
+    test->loadHtml("<html><body><p>WebKitGTK+ Inspector test</p></body></html>", 0);
+    test->waitUntilLoadFinished();
+
+    test->showAndWaitUntilFinished(false);
+    // We don't add the view to a container, so consume the weak ref with GRefPtr.
+    GRefPtr<WebKitWebViewBase> inspectorView = webkit_web_inspector_get_web_view(test->m_inspector);
+    g_assert(inspectorView.get());
+    test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inspectorView.get()));
+    g_assert(!webkit_web_inspector_is_attached(test->m_inspector));
+    g_assert_cmpuint(webkit_web_inspector_get_attached_height(test->m_inspector), ==, 0);
+    Vector<InspectorTest::InspectorEvents>& events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 2);
+    g_assert_cmpint(events[0], ==, InspectorTest::BringToFront);
+    g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow);
+    test->m_events.clear();
+
+    test->showAndWaitUntilFinished(true);
+    events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 1);
+    g_assert_cmpint(events[0], ==, InspectorTest::BringToFront);
+    test->m_events.clear();
+
+    test->resizeViewAndAttach();
+    g_assert(webkit_web_inspector_is_attached(test->m_inspector));
+    events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 1);
+    g_assert_cmpint(events[0], ==, InspectorTest::Attach);
+    test->m_events.clear();
+
+    test->detachAndWaitUntilWindowOpened();
+    g_assert(!webkit_web_inspector_is_attached(test->m_inspector));
+    events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 2);
+    g_assert_cmpint(events[0], ==, InspectorTest::Detach);
+    g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow);
+    test->m_events.clear();
+
+    test->closeAndWaitUntilClosed();
+    events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 1);
+    g_assert_cmpint(events[0], ==, InspectorTest::Closed);
+    test->m_events.clear();
+}
+
+class CustomInspectorTest: public InspectorTest {
+public:
+    MAKE_GLIB_TEST_FIXTURE(CustomInspectorTest);
+
+    CustomInspectorTest()
+        : InspectorTest()
+        , m_inspectorWindow(0)
+    {
+    }
+
+    ~CustomInspectorTest()
+    {
+        if (m_inspectorWindow)
+            gtk_widget_destroy(m_inspectorWindow);
+    }
+
+    bool openWindow()
+    {
+        g_assert(!m_inspectorWindow);
+        m_inspectorWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+        WebKitWebViewBase* inspectorView = webkit_web_inspector_get_web_view(m_inspector);
+        g_assert(inspectorView);
+        gtk_container_add(GTK_CONTAINER(m_inspectorWindow), GTK_WIDGET(inspectorView));
+        gtk_widget_show_all(m_inspectorWindow);
+
+        return InspectorTest::openWindow();
+    }
+
+    void closed()
+    {
+        if (m_inspectorWindow) {
+            gtk_widget_destroy(m_inspectorWindow);
+            m_inspectorWindow = 0;
+        }
+
+        return InspectorTest::closed();
+    }
+
+    bool attach()
+    {
+        GRefPtr<WebKitWebViewBase> inspectorView = webkit_web_inspector_get_web_view(m_inspector);
+        if (m_inspectorWindow) {
+            gtk_container_remove(GTK_CONTAINER(m_inspectorWindow), GTK_WIDGET(inspectorView.get()));
+            gtk_widget_destroy(m_inspectorWindow);
+            m_inspectorWindow = 0;
+        }
+
+        GtkWidget* pane;
+        if (gtk_bin_get_child(GTK_BIN(m_parentWindow)) == GTK_WIDGET(m_webView)) {
+            GRefPtr<WebKitWebView> inspectedView = m_webView;
+            gtk_container_remove(GTK_CONTAINER(m_parentWindow), GTK_WIDGET(m_webView));
+            pane = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
+            gtk_paned_add1(GTK_PANED(pane), GTK_WIDGET(m_webView));
+            gtk_container_add(GTK_CONTAINER(m_parentWindow), pane);
+            gtk_widget_show_all(pane);
+        } else
+            pane = gtk_bin_get_child(GTK_BIN(m_parentWindow));
+        gtk_paned_add2(GTK_PANED(pane), GTK_WIDGET(inspectorView.get()));
+
+        return InspectorTest::attach();
+    }
+
+    bool detach()
+    {
+        GRefPtr<WebKitWebViewBase> inspectorView = webkit_web_inspector_get_web_view(m_inspector);
+        GtkWidget* pane = gtk_bin_get_child(GTK_BIN(m_parentWindow));
+        g_assert(GTK_IS_PANED(pane));
+        gtk_container_remove(GTK_CONTAINER(pane), GTK_WIDGET(inspectorView.get()));
+        return InspectorTest::detach();
+    }
+
+    void destroyWindowAndWaitUntilClosed()
+    {
+        g_assert(m_inspectorWindow);
+        gtk_widget_destroy(m_inspectorWindow);
+        m_inspectorWindow = 0;
+        g_main_loop_run(m_mainLoop);
+    }
+
+    GtkWidget* m_inspectorWindow;
+};
+
+static void testInspectorManualAttachDetach(CustomInspectorTest* test, gconstpointer)
+{
+    test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
+    test->resizeView(200, 200);
+    test->loadHtml("<html><body><p>WebKitGTK+ Inspector test</p></body></html>", 0);
+    test->waitUntilLoadFinished();
+
+    test->showAndWaitUntilFinished(false);
+    test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webkit_web_inspector_get_web_view(test->m_inspector)));
+    g_assert(!webkit_web_inspector_is_attached(test->m_inspector));
+    Vector<InspectorTest::InspectorEvents>& events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 2);
+    g_assert_cmpint(events[0], ==, InspectorTest::BringToFront);
+    g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow);
+    test->m_events.clear();
+
+    test->resizeViewAndAttach();
+    g_assert(webkit_web_inspector_is_attached(test->m_inspector));
+    events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 1);
+    g_assert_cmpint(events[0], ==, InspectorTest::Attach);
+    test->m_events.clear();
+
+    test->detachAndWaitUntilWindowOpened();
+    g_assert(!webkit_web_inspector_is_attached(test->m_inspector));
+    events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 2);
+    g_assert_cmpint(events[0], ==, InspectorTest::Detach);
+    g_assert_cmpint(events[1], ==, InspectorTest::OpenWindow);
+    test->m_events.clear();
+
+    test->resizeViewAndAttach();
+    g_assert(webkit_web_inspector_is_attached(test->m_inspector));
+    test->m_events.clear();
+    test->closeAndWaitUntilClosed();
+    events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 2);
+    g_assert_cmpint(events[0], ==, InspectorTest::Detach);
+    g_assert_cmpint(events[1], ==, InspectorTest::Closed);
+    test->m_events.clear();
+}
+
+static void testInspectorCustomContainerDestroyed(CustomInspectorTest* test, gconstpointer)
+{
+    test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
+    test->resizeView(200, 200);
+    test->loadHtml("<html><body><p>WebKitGTK+ Inspector test</p></body></html>", 0);
+    test->waitUntilLoadFinished();
+
+    test->showAndWaitUntilFinished(false);
+    test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webkit_web_inspector_get_web_view(test->m_inspector)));
+    g_assert(!webkit_web_inspector_is_attached(test->m_inspector));
+
+    test->m_events.clear();
+    test->destroyWindowAndWaitUntilClosed();
+    Vector<InspectorTest::InspectorEvents>& events = test->m_events;
+    g_assert_cmpint(events.size(), ==, 1);
+    g_assert_cmpint(events[0], ==, InspectorTest::Closed);
+    test->m_events.clear();
+}
+
+void beforeAll()
+{
+    g_setenv("WEBKIT_INSPECTOR_PATH", WEBKIT_INSPECTOR_PATH, FALSE);
+    InspectorTest::add("WebKitWebInspector", "default", testInspectorDefault);
+    CustomInspectorTest::add("WebKitWebInspector", "manual-attach-detach", testInspectorManualAttachDetach);
+    CustomInspectorTest::add("WebKitWebInspector", "custom-container-destroyed", testInspectorCustomContainerDestroyed);
+}
+
+void afterAll()
+{
+}
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp
index 83d4b02..e355f78 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.cpp
@@ -162,10 +162,10 @@
     return FALSE;
 }
 
-void WebViewTest::showInWindowAndWaitUntilMapped()
+void WebViewTest::showInWindowAndWaitUntilMapped(GtkWindowType windowType)
 {
     g_assert(!m_parentWindow);
-    m_parentWindow = gtk_window_new(GTK_WINDOW_POPUP);
+    m_parentWindow = gtk_window_new(windowType);
     gtk_container_add(GTK_CONTAINER(m_parentWindow), GTK_WIDGET(m_webView));
     gtk_widget_show(GTK_WIDGET(m_webView));
 
@@ -174,6 +174,17 @@
     g_main_loop_run(m_mainLoop);
 }
 
+void WebViewTest::resizeView(int width, int height)
+{
+    GtkAllocation allocation;
+    gtk_widget_get_allocation(GTK_WIDGET(m_webView), &allocation);
+    if (width != -1)
+        allocation.width = width;
+    if (height != -1)
+        allocation.height = height;
+    gtk_widget_size_allocate(GTK_WIDGET(m_webView), &allocation);
+}
+
 void WebViewTest::mouseMoveTo(int x, int y, unsigned int mouseModifiers)
 {
     g_assert(m_parentWindow);
diff --git a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h
index 92e1236..ff6a8c7 100644
--- a/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h
+++ b/Source/WebKit2/UIProcess/API/gtk/tests/WebViewTest.h
@@ -44,7 +44,8 @@
     void waitUntilLoadFinished();
     void waitUntilTitleChangedTo(const char* expectedTitle);
     void waitUntilTitleChanged();
-    void showInWindowAndWaitUntilMapped();
+    void showInWindowAndWaitUntilMapped(GtkWindowType = GTK_WINDOW_POPUP);
+    void resizeView(int width, int height);
 
     void mouseMoveTo(int x, int y, unsigned int mouseModifiers = 0);
     void clickMouseButton(int x, int y, unsigned int button = 1, unsigned int mouseModifiers = 0);
diff --git a/Source/WebKit2/UIProcess/API/gtk/webkit2.h b/Source/WebKit2/UIProcess/API/gtk/webkit2.h
index 7699c49..23dbd99 100644
--- a/Source/WebKit2/UIProcess/API/gtk/webkit2.h
+++ b/Source/WebKit2/UIProcess/API/gtk/webkit2.h
@@ -43,6 +43,7 @@
 #include <webkit2/WebKitURIRequest.h>
 #include <webkit2/WebKitURIResponse.h>
 #include <webkit2/WebKitWebContext.h>
+#include <webkit2/WebKitWebInspector.h>
 #include <webkit2/WebKitWebResource.h>
 #include <webkit2/WebKitWebView.h>
 #include <webkit2/WebKitWebViewBase.h>
diff --git a/Source/WebKit2/UIProcess/WebInspectorProxy.h b/Source/WebKit2/UIProcess/WebInspectorProxy.h
index ea2640e..02cf52c 100644
--- a/Source/WebKit2/UIProcess/WebInspectorProxy.h
+++ b/Source/WebKit2/UIProcess/WebInspectorProxy.h
@@ -48,6 +48,10 @@
 #include <WebCore/WindowMessageListener.h>
 #endif
 
+#if PLATFORM(GTK)
+#include "WebInspectorClientGtk.h"
+#endif
+
 namespace WebKit {
 
 class WebFrameProxy;
@@ -91,6 +95,11 @@
     void inspectedViewFrameDidChange();
 #endif
 
+#if PLATFORM(GTK)
+    GtkWidget* inspectorView() const { return m_inspectorView; };
+    void initializeInspectorClientGtk(const WKInspectorClientGtk*);
+#endif
+
     void showConsole();
     void showResources();
     void showMainResourceForFrame(WebFrameProxy*);
@@ -204,6 +213,7 @@
     HWND m_inspectorWindow;
     RefPtr<WebView> m_inspectorView;
 #elif PLATFORM(GTK)
+    WebInspectorClientGtk m_client;
     GtkWidget* m_inspectorView;
     GtkWidget* m_inspectorWindow;
 #endif
diff --git a/Source/WebKit2/UIProcess/gtk/WebInspectorClientGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebInspectorClientGtk.cpp
new file mode 100644
index 0000000..448f423
--- /dev/null
+++ b/Source/WebKit2/UIProcess/gtk/WebInspectorClientGtk.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebInspectorClientGtk.h"
+
+#include "WKAPICast.h"
+#include "WKSharedAPICast.h"
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+bool WebInspectorClientGtk::openWindow(WebInspectorProxy* inspector)
+{
+    if (!m_client.openWindow)
+        return false;
+    return m_client.openWindow(toAPI(inspector), m_client.clientInfo);
+}
+
+void WebInspectorClientGtk::didClose(WebInspectorProxy* inspector)
+{
+    if (!m_client.didClose)
+        return;
+    m_client.didClose(toAPI(inspector), m_client.clientInfo);
+}
+
+bool WebInspectorClientGtk::bringToFront(WebInspectorProxy* inspector)
+{
+    if (!m_client.bringToFront)
+        return false;
+    return m_client.bringToFront(toAPI(inspector), m_client.clientInfo);
+}
+
+void WebInspectorClientGtk::inspectedURLChanged(WebInspectorProxy* inspector, const String& url)
+{
+    if (!m_client.inspectedURLChanged)
+        return;
+    m_client.inspectedURLChanged(toAPI(inspector), toAPI(url.impl()), m_client.clientInfo);
+}
+
+bool WebInspectorClientGtk::attach(WebInspectorProxy* inspector)
+{
+    if (!m_client.attach)
+        return false;
+    return m_client.attach(toAPI(inspector), m_client.clientInfo);
+}
+
+bool WebInspectorClientGtk::detach(WebInspectorProxy* inspector)
+{
+    if (!m_client.detach)
+        return false;
+    return m_client.detach(toAPI(inspector), m_client.clientInfo);
+}
+
+void WebInspectorClientGtk::didChangeAttachedHeight(WebInspectorProxy* inspector, unsigned height)
+{
+    if (!m_client.didChangeAttachedHeight)
+        return;
+    m_client.didChangeAttachedHeight(toAPI(inspector), height, m_client.clientInfo);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/gtk/WebInspectorClientGtk.h b/Source/WebKit2/UIProcess/gtk/WebInspectorClientGtk.h
new file mode 100644
index 0000000..89d0f73
--- /dev/null
+++ b/Source/WebKit2/UIProcess/gtk/WebInspectorClientGtk.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebInspectorClientGtk_h
+#define WebInspectorClientGtk_h
+
+#include "APIClient.h"
+#include "WKInspectorClientGtk.h"
+
+#include <wtf/text/WTFString.h>
+
+namespace WebKit {
+
+class APIObject;
+class WebInspectorProxy;
+
+class WebInspectorClientGtk : public APIClient<WKInspectorClientGtk, kWKInspectorClientGtkCurrentVersion> {
+public:
+    bool openWindow(WebInspectorProxy*);
+    void didClose(WebInspectorProxy*);
+    bool bringToFront(WebInspectorProxy*);
+    void inspectedURLChanged(WebInspectorProxy*, const String& url);
+    bool attach(WebInspectorProxy*);
+    bool detach(WebInspectorProxy*);
+    void didChangeAttachedHeight(WebInspectorProxy*, unsigned height);
+};
+
+} // namespace WebKit
+
+#endif // WebInspectorClientGtk_h
diff --git a/Source/WebKit2/UIProcess/gtk/WebInspectorProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebInspectorProxyGtk.cpp
index 7d27dfd..425d799 100644
--- a/Source/WebKit2/UIProcess/gtk/WebInspectorProxyGtk.cpp
+++ b/Source/WebKit2/UIProcess/gtk/WebInspectorProxyGtk.cpp
@@ -54,15 +54,18 @@
     return inspectorFilesPath;
 }
 
-static gboolean inspectorWindowClosed(GtkWidget* window, GdkEvent*, gpointer userData)
+static void inspectorViewDestroyed(GtkWidget*, gpointer userData)
 {
     WebInspectorProxy* inspectorProxy = static_cast<WebInspectorProxy*>(userData);
 
     // Inform WebProcess about webinspector closure. Not doing so,
     // results in failure of subsequent invocation of webinspector.
     inspectorProxy->close();
+}
 
-    return FALSE;
+void WebInspectorProxy::initializeInspectorClientGtk(const WKInspectorClientGtk* inspectorClient)
+{
+    m_client.initialize(inspectorClient);
 }
 
 WebPageProxy* WebInspectorProxy::platformCreateInspectorPage()
@@ -70,11 +73,15 @@
     ASSERT(m_page);
     ASSERT(!m_inspectorView);
     m_inspectorView = GTK_WIDGET(webkitWebViewBaseCreate(page()->process()->context(), inspectorPageGroup()));
+    g_object_add_weak_pointer(G_OBJECT(m_inspectorView), reinterpret_cast<void**>(&m_inspectorView));
     return webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_inspectorView));
 }
 
 void WebInspectorProxy::createInspectorWindow()
 {
+    if (m_client.openWindow(this))
+        return;
+
     ASSERT(!m_inspectorWindow);
     m_inspectorWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 
@@ -84,7 +91,6 @@
 
     gtk_window_set_title(GTK_WINDOW(m_inspectorWindow), _("Web Inspector"));
     gtk_window_set_default_size(GTK_WINDOW(m_inspectorWindow), initialWindowWidth, initialWindowHeight);
-    g_signal_connect(m_inspectorWindow, "delete-event", G_CALLBACK(inspectorWindowClosed), this);
 
     gtk_container_add(GTK_CONTAINER(m_inspectorWindow), m_inspectorView);
     gtk_widget_show(m_inspectorView);
@@ -102,10 +108,16 @@
         platformAttach();
     else
         createInspectorWindow();
+    g_signal_connect(m_inspectorView, "destroy", G_CALLBACK(inspectorViewDestroyed), this);
 }
 
 void WebInspectorProxy::platformDidClose()
 {
+    if (m_inspectorView)
+        g_signal_handlers_disconnect_by_func(m_inspectorView, reinterpret_cast<void*>(inspectorViewDestroyed), this);
+
+    m_client.didClose(this);
+
     if (m_inspectorWindow) {
         gtk_widget_destroy(m_inspectorWindow);
         m_inspectorWindow = 0;
@@ -115,6 +127,9 @@
 
 void WebInspectorProxy::platformBringToFront()
 {
+    if (m_client.bringToFront(this))
+        return;
+
     GtkWidget* parent = gtk_widget_get_toplevel(m_inspectorView);
     if (WebCore::widgetIsOnscreenToplevelWindow(parent))
         gtk_window_present(GTK_WINDOW(parent));
@@ -130,6 +145,8 @@
 
 void WebInspectorProxy::platformInspectedURLChanged(const String& url)
 {
+    m_client.inspectedURLChanged(this, url);
+
     if (!m_inspectorWindow)
         return;
     GOwnPtr<gchar> title(g_strdup_printf("%s - %s", _("Web Inspector"), url.utf8().data()));
@@ -165,6 +182,9 @@
         m_inspectorWindow = 0;
     }
 
+    if (m_client.attach(this))
+        return;
+
     gtk_container_add(GTK_CONTAINER(m_page->viewWidget()), m_inspectorView);
     gtk_widget_show(m_inspectorView);
 }
@@ -175,7 +195,9 @@
         return;
 
     GRefPtr<GtkWidget> inspectorView = m_inspectorView;
-    gtk_container_remove(GTK_CONTAINER(m_page->viewWidget()), m_inspectorView);
+    if (!m_client.detach(this))
+        gtk_container_remove(GTK_CONTAINER(m_page->viewWidget()), m_inspectorView);
+
     if (!m_isVisible)
         return;
 
@@ -186,6 +208,8 @@
 {
     if (!m_isAttached)
         return;
+
+    m_client.didChangeAttachedHeight(this, height);
     webkitWebViewBaseSetInspectorViewHeight(WEBKIT_WEB_VIEW_BASE(m_page->viewWidget()), height);
 }