tizen beta release
[profile/ivi/webkit-efl.git] / Source / WebKit / gtk / WebCoreSupport / InspectorClientGtk.cpp
1 /*
2  * Copyright (C) 2008 Gustavo Noronha Silva
3  * Copyright (C) 2010 Collabora Ltd.
4  *
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.
9  *
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.
14  *
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
18  */
19
20 #include "config.h"
21 #include "InspectorClientGtk.h"
22
23 #include "Frame.h"
24 #include "InspectorController.h"
25 #include "NotImplemented.h"
26 #include "Page.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>
34
35 using namespace WebCore;
36
37 namespace WebKit {
38
39 static void notifyWebViewDestroyed(WebKitWebView* webView, InspectorFrontendClient* inspectorFrontendClient)
40 {
41     inspectorFrontendClient->destroyInspectorWindow(true);
42 }
43
44 namespace {
45
46 class InspectorFrontendSettingsGtk : public InspectorFrontendClientLocal::Settings {
47 public:
48     virtual ~InspectorFrontendSettingsGtk() { }
49
50 private:
51 #ifdef HAVE_GSETTINGS
52     static bool shouldIgnoreSetting(const String& key)
53     {
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());
59         return true;
60     }
61
62     virtual String getProperty(const String& name)
63     {
64         if (shouldIgnoreSetting(name))
65             return String();
66
67         GSettings* settings = inspectorGSettings();
68         if (!settings)
69             return String();
70
71         GRefPtr<GVariant> variant = adoptGRef(g_settings_get_value(settings, name.utf8().data()));
72         return String(g_variant_get_string(variant.get(), 0));
73     }
74
75     virtual void setProperty(const String& name, const String& value)
76     {
77         // Avoid setting unknown keys to avoid aborting the execution.
78         if (shouldIgnoreSetting(name))
79             return;
80
81         GSettings* settings = inspectorGSettings();
82         if (!settings)
83             return;
84
85         GRefPtr<GVariant> variant = adoptGRef(g_variant_new_string(value.utf8().data()));
86         g_settings_set_value(settings, name.utf8().data(), variant.get());
87     }
88 #else
89     virtual String getProperty(const String&)
90     {
91         notImplemented();
92         return String();
93     }
94
95     virtual void setProperty(const String&, const String&)
96     {
97         notImplemented();
98     }
99 #endif // HAVE_GSETTINGS
100 };
101
102 } // namespace
103
104 InspectorClient::InspectorClient(WebKitWebView* webView)
105     : m_inspectedWebView(webView)
106     , m_frontendPage(0)
107     , m_frontendClient(0)
108 {}
109
110 InspectorClient::~InspectorClient()
111 {
112     if (m_frontendClient) {
113         m_frontendClient->disconnectInspectorClient();
114         m_frontendClient = 0;
115     }
116 }
117
118 void InspectorClient::inspectorDestroyed()
119 {
120     closeInspectorFrontend();
121     delete this;
122 }
123
124 void InspectorClient::openInspectorFrontend(InspectorController* controller)
125 {
126     // This g_object_get will ref the inspector. We're not doing an
127     // unref if this method succeeds because the inspector object must
128     // be alive even after the inspected WebView is destroyed - the
129     // close-window and destroy signals still need to be
130     // emitted.
131     WebKitWebInspector* webInspector = 0;
132     g_object_get(m_inspectedWebView, "web-inspector", &webInspector, NULL);
133     ASSERT(webInspector);
134
135     WebKitWebView* inspectorWebView = 0;
136     g_signal_emit_by_name(webInspector, "inspect-web-view", m_inspectedWebView, &inspectorWebView);
137
138     if (!inspectorWebView) {
139         g_object_unref(webInspector);
140         return;
141     }
142
143     webkit_web_inspector_set_web_view(webInspector, inspectorWebView);
144  
145     GOwnPtr<gchar> inspectorPath(g_build_filename(inspectorFilesPath(), "inspector.html", NULL));
146     GOwnPtr<gchar> inspectorURI(g_filename_to_uri(inspectorPath.get(), 0, 0));
147     webkit_web_view_load_uri(inspectorWebView, inspectorURI.get());
148
149     gtk_widget_show(GTK_WIDGET(inspectorWebView));
150
151     m_frontendPage = core(inspectorWebView);
152     OwnPtr<InspectorFrontendClient> frontendClient = adoptPtr(new InspectorFrontendClient(m_inspectedWebView, inspectorWebView, webInspector, m_frontendPage, this));
153     m_frontendClient = frontendClient.get();
154     m_frontendPage->inspectorController()->setInspectorFrontendClient(frontendClient.release());
155
156     // The inspector must be in it's own PageGroup to avoid deadlock while debugging.
157     m_frontendPage->setGroupName("");
158 }
159
160 void InspectorClient::closeInspectorFrontend()
161 {
162     if (m_frontendClient)
163         m_frontendClient->destroyInspectorWindow(false);
164 }
165
166 void InspectorClient::bringFrontendToFront()
167 {
168     m_frontendClient->bringToFront();
169 }
170
171 void InspectorClient::releaseFrontendPage()
172 {
173     m_frontendPage = 0;
174 }
175
176 void InspectorClient::highlight()
177 {
178     hideHighlight();
179 }
180
181 void InspectorClient::hideHighlight()
182 {
183     // FIXME: we should be able to only invalidate the actual rects of
184     // the new and old nodes. We need to track the nodes, and take the
185     // actual highlight size into account when calculating the damage
186     // rect.
187     gtk_widget_queue_draw(GTK_WIDGET(m_inspectedWebView));
188 }
189
190 bool InspectorClient::sendMessageToFrontend(const String& message)
191 {
192     return doDispatchMessageOnFrontendPage(m_frontendPage, message);
193 }
194
195 const char* InspectorClient::inspectorFilesPath()
196 {
197     if (m_inspectorFilesPath)
198         m_inspectorFilesPath.get();
199
200     const char* environmentPath = getenv("WEBKIT_INSPECTOR_PATH");
201     if (environmentPath && g_file_test(environmentPath, G_FILE_TEST_IS_DIR))
202         m_inspectorFilesPath.set(g_strdup(environmentPath));
203     else
204         m_inspectorFilesPath.set(g_build_filename(DATA_DIR, "webkitgtk-"WEBKITGTK_API_VERSION_STRING, "webinspector", NULL));
205
206     return m_inspectorFilesPath.get();
207 }
208
209 InspectorFrontendClient::InspectorFrontendClient(WebKitWebView* inspectedWebView, WebKitWebView* inspectorWebView, WebKitWebInspector* webInspector, Page* inspectorPage, InspectorClient* inspectorClient)
210     : InspectorFrontendClientLocal(core(inspectedWebView)->inspectorController(), inspectorPage, adoptPtr(new InspectorFrontendSettingsGtk()))
211     , m_inspectorWebView(inspectorWebView)
212     , m_inspectedWebView(inspectedWebView)
213     , m_webInspector(webInspector)
214     , m_inspectorClient(inspectorClient)
215 {
216     g_signal_connect(m_inspectorWebView, "destroy",
217                      G_CALLBACK(notifyWebViewDestroyed), (gpointer)this);
218 }
219
220 InspectorFrontendClient::~InspectorFrontendClient()
221 {
222     if (m_inspectorClient) {
223         m_inspectorClient->disconnectFrontendClient();
224         m_inspectorClient = 0;
225     }
226     ASSERT(!m_webInspector);
227 }
228
229 void InspectorFrontendClient::destroyInspectorWindow(bool notifyInspectorController)
230 {
231     if (!m_webInspector)
232         return;
233     WebKitWebInspector* webInspector = m_webInspector;
234     m_webInspector = 0;
235
236     g_signal_handlers_disconnect_by_func(m_inspectorWebView, (gpointer)notifyWebViewDestroyed, (gpointer)this);
237     m_inspectorWebView = 0;
238
239     if (notifyInspectorController)
240         core(m_inspectedWebView)->inspectorController()->disconnectFrontend();
241
242     if (m_inspectorClient)
243         m_inspectorClient->releaseFrontendPage();
244
245     gboolean handled = FALSE;
246     g_signal_emit_by_name(webInspector, "close-window", &handled);
247     ASSERT(handled);
248
249     // Please do not use member variables here because InspectorFrontendClient object pointed by 'this'
250     // has been implicitly deleted by "close-window" function.
251
252     /* we should now dispose our own reference */
253     g_object_unref(webInspector);
254 }
255
256 String InspectorFrontendClient::localizedStringsURL()
257 {
258     GOwnPtr<gchar> stringsPath(g_build_filename(m_inspectorClient->inspectorFilesPath(), "localizedStrings.js", NULL));
259     GOwnPtr<gchar> stringsURI(g_filename_to_uri(stringsPath.get(), 0, 0));
260
261     // FIXME: support l10n of localizedStrings.js
262     return String::fromUTF8(stringsURI.get());
263 }
264
265 String InspectorFrontendClient::hiddenPanels()
266 {
267     notImplemented();
268     return String();
269 }
270
271 void InspectorFrontendClient::bringToFront()
272 {
273     if (!m_inspectorWebView)
274         return;
275
276     gboolean handled = FALSE;
277     g_signal_emit_by_name(m_webInspector, "show-window", &handled);
278 }
279
280 void InspectorFrontendClient::closeWindow()
281 {
282     destroyInspectorWindow(true);
283 }
284
285 void InspectorFrontendClient::attachWindow()
286 {
287     if (!m_inspectorWebView)
288         return;
289
290     gboolean handled = FALSE;
291     g_signal_emit_by_name(m_webInspector, "attach-window", &handled);
292 }
293
294 void InspectorFrontendClient::detachWindow()
295 {
296     if (!m_inspectorWebView)
297         return;
298
299     gboolean handled = FALSE;
300     g_signal_emit_by_name(m_webInspector, "detach-window", &handled);
301 }
302
303 void InspectorFrontendClient::setAttachedWindowHeight(unsigned height)
304 {
305     notImplemented();
306 }
307
308 void InspectorFrontendClient::inspectedURLChanged(const String& newURL)
309 {
310     if (!m_inspectorWebView)
311         return;
312
313     webkit_web_inspector_set_inspected_uri(m_webInspector, newURL.utf8().data());
314 }
315
316 }
317