2 * Copyright (C) 2008 Gustavo Noronha Silva
3 * Copyright (C) 2010 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "InspectorClientGtk.h"
24 #include "InspectorController.h"
25 #include "NotImplemented.h"
27 #include "PlatformString.h"
28 #include "webkitversion.h"
29 #include "webkitwebinspector.h"
30 #include "webkitwebinspectorprivate.h"
31 #include "webkitwebview.h"
32 #include "webkitwebviewprivate.h"
33 #include <wtf/text/CString.h>
35 using namespace WebCore;
39 static void notifyWebViewDestroyed(WebKitWebView* webView, InspectorFrontendClient* inspectorFrontendClient)
41 inspectorFrontendClient->destroyInspectorWindow(true);
46 class InspectorFrontendSettingsGtk : public InspectorFrontendClientLocal::Settings {
48 virtual ~InspectorFrontendSettingsGtk() { }
52 static bool shouldIgnoreSetting(const String& key)
54 // GSettings considers trying to fetch or set a setting that is
55 // not backed by a schema as programmer error, and aborts the
56 // program's execution. We check here to avoid having an unhandled
57 // setting as a fatal error.
58 LOG_VERBOSE(NotYetImplemented, "Unknown key ignored: %s", key.ascii().data());
62 virtual String getProperty(const String& name)
64 if (shouldIgnoreSetting(name))
67 GSettings* settings = inspectorGSettings();
71 GRefPtr<GVariant> variant = adoptGRef(g_settings_get_value(settings, name.utf8().data()));
72 return String(g_variant_get_string(variant.get(), 0));
75 virtual void setProperty(const String& name, const String& value)
77 // Avoid setting unknown keys to avoid aborting the execution.
78 if (shouldIgnoreSetting(name))
81 GSettings* settings = inspectorGSettings();
85 GRefPtr<GVariant> variant = adoptGRef(g_variant_new_string(value.utf8().data()));
86 g_settings_set_value(settings, name.utf8().data(), variant.get());
89 virtual String getProperty(const String&)
95 virtual void setProperty(const String&, const String&)
99 #endif // HAVE_GSETTINGS
104 InspectorClient::InspectorClient(WebKitWebView* webView)
105 : m_inspectedWebView(webView)
107 , m_frontendClient(0)
110 InspectorClient::~InspectorClient()
112 if (m_frontendClient) {
113 m_frontendClient->disconnectInspectorClient();
114 m_frontendClient = 0;
118 void InspectorClient::inspectorDestroyed()
123 void InspectorClient::openInspectorFrontend(InspectorController* controller)
125 // This g_object_get will ref the inspector. We're not doing an
126 // unref if this method succeeds because the inspector object must
127 // be alive even after the inspected WebView is destroyed - the
128 // close-window and destroy signals still need to be
130 WebKitWebInspector* webInspector = 0;
131 g_object_get(m_inspectedWebView, "web-inspector", &webInspector, NULL);
132 ASSERT(webInspector);
134 WebKitWebView* inspectorWebView = 0;
135 g_signal_emit_by_name(webInspector, "inspect-web-view", m_inspectedWebView, &inspectorWebView);
137 if (!inspectorWebView) {
138 g_object_unref(webInspector);
142 webkit_web_inspector_set_web_view(webInspector, inspectorWebView);
144 GOwnPtr<gchar> inspectorPath(g_build_filename(inspectorFilesPath(), "inspector.html", NULL));
145 GOwnPtr<gchar> inspectorURI(g_filename_to_uri(inspectorPath.get(), 0, 0));
146 webkit_web_view_load_uri(inspectorWebView, inspectorURI.get());
148 gtk_widget_show(GTK_WIDGET(inspectorWebView));
150 m_frontendPage = core(inspectorWebView);
151 OwnPtr<InspectorFrontendClient> frontendClient = adoptPtr(new InspectorFrontendClient(m_inspectedWebView, inspectorWebView, webInspector, m_frontendPage, this));
152 m_frontendClient = frontendClient.get();
153 m_frontendPage->inspectorController()->setInspectorFrontendClient(frontendClient.release());
155 // The inspector must be in it's own PageGroup to avoid deadlock while debugging.
156 m_frontendPage->setGroupName("");
159 void InspectorClient::releaseFrontendPage()
164 void InspectorClient::highlight()
169 void InspectorClient::hideHighlight()
171 // FIXME: we should be able to only invalidate the actual rects of
172 // the new and old nodes. We need to track the nodes, and take the
173 // actual highlight size into account when calculating the damage
175 gtk_widget_queue_draw(GTK_WIDGET(m_inspectedWebView));
178 bool InspectorClient::sendMessageToFrontend(const String& message)
180 return doDispatchMessageOnFrontendPage(m_frontendPage, message);
183 const char* InspectorClient::inspectorFilesPath()
185 if (m_inspectorFilesPath)
186 m_inspectorFilesPath.get();
188 const char* environmentPath = getenv("WEBKIT_INSPECTOR_PATH");
189 if (environmentPath && g_file_test(environmentPath, G_FILE_TEST_IS_DIR))
190 m_inspectorFilesPath.set(g_strdup(environmentPath));
192 m_inspectorFilesPath.set(g_build_filename(DATA_DIR, "webkitgtk-"WEBKITGTK_API_VERSION_STRING, "webinspector", NULL));
194 return m_inspectorFilesPath.get();
197 InspectorFrontendClient::InspectorFrontendClient(WebKitWebView* inspectedWebView, WebKitWebView* inspectorWebView, WebKitWebInspector* webInspector, Page* inspectorPage, InspectorClient* inspectorClient)
198 : InspectorFrontendClientLocal(core(inspectedWebView)->inspectorController(), inspectorPage, adoptPtr(new InspectorFrontendSettingsGtk()))
199 , m_inspectorWebView(inspectorWebView)
200 , m_inspectedWebView(inspectedWebView)
201 , m_webInspector(webInspector)
202 , m_inspectorClient(inspectorClient)
204 g_signal_connect(m_inspectorWebView, "destroy",
205 G_CALLBACK(notifyWebViewDestroyed), (gpointer)this);
208 InspectorFrontendClient::~InspectorFrontendClient()
210 if (m_inspectorClient) {
211 m_inspectorClient->disconnectFrontendClient();
212 m_inspectorClient = 0;
214 ASSERT(!m_webInspector);
217 void InspectorFrontendClient::destroyInspectorWindow(bool notifyInspectorController)
221 WebKitWebInspector* webInspector = m_webInspector;
224 g_signal_handlers_disconnect_by_func(m_inspectorWebView, (gpointer)notifyWebViewDestroyed, (gpointer)this);
225 m_inspectorWebView = 0;
227 if (notifyInspectorController)
228 core(m_inspectedWebView)->inspectorController()->disconnectFrontend();
230 if (m_inspectorClient)
231 m_inspectorClient->releaseFrontendPage();
233 gboolean handled = FALSE;
234 g_signal_emit_by_name(webInspector, "close-window", &handled);
237 // Please do not use member variables here because InspectorFrontendClient object pointed by 'this'
238 // has been implicitly deleted by "close-window" function.
240 /* we should now dispose our own reference */
241 g_object_unref(webInspector);
244 String InspectorFrontendClient::localizedStringsURL()
246 GOwnPtr<gchar> stringsPath(g_build_filename(m_inspectorClient->inspectorFilesPath(), "localizedStrings.js", NULL));
247 GOwnPtr<gchar> stringsURI(g_filename_to_uri(stringsPath.get(), 0, 0));
249 // FIXME: support l10n of localizedStrings.js
250 return String::fromUTF8(stringsURI.get());
253 String InspectorFrontendClient::hiddenPanels()
259 void InspectorFrontendClient::bringToFront()
261 if (!m_inspectorWebView)
264 gboolean handled = FALSE;
265 g_signal_emit_by_name(m_webInspector, "show-window", &handled);
268 void InspectorFrontendClient::closeWindow()
270 destroyInspectorWindow(true);
273 void InspectorFrontendClient::disconnectFromBackend()
275 destroyInspectorWindow(false);
278 void InspectorFrontendClient::attachWindow()
280 if (!m_inspectorWebView)
283 gboolean handled = FALSE;
284 g_signal_emit_by_name(m_webInspector, "attach-window", &handled);
287 void InspectorFrontendClient::detachWindow()
289 if (!m_inspectorWebView)
292 gboolean handled = FALSE;
293 g_signal_emit_by_name(m_webInspector, "detach-window", &handled);
296 void InspectorFrontendClient::setAttachedWindowHeight(unsigned height)
301 void InspectorFrontendClient::inspectedURLChanged(const String& newURL)
303 if (!m_inspectorWebView)
306 webkit_web_inspector_set_inspected_uri(m_webInspector, newURL.utf8().data());