• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Gustavo Noronha Silva
3  * Copyright (C) 2008, 2009 Holger Hans Peter Freyther
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "config.h"
22 
23 #include <glib/gi18n-lib.h>
24 #include "webkitwebinspector.h"
25 #include "webkitmarshal.h"
26 #include "InspectorClientGtk.h"
27 #include "webkitprivate.h"
28 
29 /**
30  * SECTION:webkitwebinspector
31  * @short_description: Access to the WebKit Inspector
32  *
33  * The WebKit Inspector is a graphical tool to inspect and change
34  * the content of a #WebKitWebView. It also includes an interactive
35  * JavaScriptDebugger. Using this class one can get a GtkWidget which
36  * can be embedded into an application to show the inspector.
37  *
38  * The inspector is available when the #WebKitWebSettings of the
39  * #WebKitWebView has set the #WebKitWebSettings:enable-developer-extras
40  * to true otherwise no inspector is available.
41  *
42  * <informalexample><programlisting>
43  * /<!-- -->* Enable the developer extras *<!-- -->/
44  * WebKitWebSettings *setting = webkit_web_view_get_settings (WEBKIT_WEB_VIEW(my_webview));
45  * g_object_set (G_OBJECT(settings), "enable-developer-extras", TRUE, NULL);
46  *
47  * /<!-- -->* load some data or reload to be able to inspect the page*<!-- -->/
48  * webkit_web_view_open (WEBKIT_WEB_VIEW(my_webview), "http://www.gnome.org");
49  *
50  * /<!-- -->* Embed the inspector somewhere *<!-- -->/
51  * WebKitWebInspector *inspector = webkit_web_view_get_inspector (WEBKIT_WEB_VIEW(my_webview));
52  * g_signal_connect (G_OBJECT (inspector), "inspect-web-view", G_CALLBACK(create_gtk_window_around_it), NULL);
53  * g_signal_connect (G_OBJECT (inspector), "show-window", G_CALLBACK(show_inpector_window), NULL));
54  * g_signal_connect (G_OBJECT (inspector), "notify::inspected-uri", G_CALLBACK(inspected_uri_changed_do_stuff), NULL);
55  * </programlisting></informalexample>
56  */
57 
58 using namespace WebKit;
59 
60 enum {
61     INSPECT_WEB_VIEW,
62     SHOW_WINDOW,
63     ATTACH_WINDOW,
64     DETACH_WINDOW,
65     CLOSE_WINDOW,
66     FINISHED,
67     LAST_SIGNAL
68 };
69 
70 static guint webkit_web_inspector_signals[LAST_SIGNAL] = { 0, };
71 
72 enum {
73     PROP_0,
74 
75     PROP_WEB_VIEW,
76     PROP_INSPECTED_URI,
77     PROP_JAVASCRIPT_PROFILING_ENABLED
78 };
79 
80 G_DEFINE_TYPE(WebKitWebInspector, webkit_web_inspector, G_TYPE_OBJECT)
81 
82 struct _WebKitWebInspectorPrivate {
83     WebCore::Page* page;
84     WebKitWebView* inspector_view;
85     gchar* inspected_uri;
86 };
87 
88 #define WEBKIT_WEB_INSPECTOR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspectorPrivate))
89 
90 static void webkit_web_inspector_finalize(GObject* object);
91 
92 static void webkit_web_inspector_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec);
93 
94 static void webkit_web_inspector_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec);
95 
webkit_inspect_web_view_request_handled(GSignalInvocationHint * ihint,GValue * returnAccu,const GValue * handlerReturn,gpointer dummy)96 static gboolean webkit_inspect_web_view_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
97 {
98     gboolean continueEmission = TRUE;
99     gpointer newWebView = g_value_get_object(handlerReturn);
100     g_value_set_object(returnAccu, newWebView);
101 
102     if (newWebView)
103         continueEmission = FALSE;
104 
105     return continueEmission;
106 }
107 
webkit_web_inspector_class_init(WebKitWebInspectorClass * klass)108 static void webkit_web_inspector_class_init(WebKitWebInspectorClass* klass)
109 {
110     GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
111     gobject_class->finalize = webkit_web_inspector_finalize;
112     gobject_class->set_property = webkit_web_inspector_set_property;
113     gobject_class->get_property = webkit_web_inspector_get_property;
114 
115     /**
116      * WebKitWebInspector::inspect-web-view:
117      * @web_inspector: the object on which the signal is emitted
118      * @web_view: the #WebKitWeb which will be inspected
119      * @return: a newly allocated #WebKitWebView or %NULL
120      *
121      * Emitted when the user activates the 'inspect' context menu item
122      * to inspect a web view. The application which is interested in
123      * the inspector should create a window, or otherwise add the
124      * #WebKitWebView it creates to an existing window.
125      *
126      * You don't need to handle the reference count of the
127      * #WebKitWebView instance you create; the widget to which you add
128      * it will do that.
129      *
130      * Since: 1.0.3
131      */
132     webkit_web_inspector_signals[INSPECT_WEB_VIEW] = g_signal_new("inspect-web-view",
133             G_TYPE_FROM_CLASS(klass),
134             (GSignalFlags)G_SIGNAL_RUN_LAST,
135             0,
136             webkit_inspect_web_view_request_handled,
137             NULL,
138             webkit_marshal_OBJECT__OBJECT,
139             WEBKIT_TYPE_WEB_VIEW , 1,
140             WEBKIT_TYPE_WEB_VIEW);
141 
142     /**
143      * WebKitWebInspector::show-window:
144      * @web_inspector: the object on which the signal is emitted
145      * @return: %TRUE if the signal has been handled
146      *
147      * Emitted when the inspector window should be displayed. Notice
148      * that the window must have been created already by handling
149      * #WebKitWebInspector::inspect-web-view.
150      *
151      * Since: 1.0.3
152      */
153     webkit_web_inspector_signals[SHOW_WINDOW] = g_signal_new("show-window",
154             G_TYPE_FROM_CLASS(klass),
155             (GSignalFlags)G_SIGNAL_RUN_LAST,
156             0,
157             g_signal_accumulator_true_handled,
158             NULL,
159             webkit_marshal_BOOLEAN__VOID,
160             G_TYPE_BOOLEAN , 0);
161 
162     /**
163      * WebKitWebInspector::attach-window:
164      * @web_inspector: the object on which the signal is emitted
165      * @return: %TRUE if the signal has been handled
166      *
167      * Emitted when the inspector should appear at the same window as
168      * the #WebKitWebView being inspected.
169      *
170      * Since: 1.0.3
171      */
172     webkit_web_inspector_signals[ATTACH_WINDOW] = g_signal_new("attach-window",
173             G_TYPE_FROM_CLASS(klass),
174             (GSignalFlags)G_SIGNAL_RUN_LAST,
175             0,
176             g_signal_accumulator_true_handled,
177             NULL,
178             webkit_marshal_BOOLEAN__VOID,
179             G_TYPE_BOOLEAN , 0);
180 
181     /**
182      * WebKitWebInspector::detach-window:
183      * @web_inspector: the object on which the signal is emitted
184      * @return: %TRUE if the signal has been handled
185      *
186      * Emitted when the inspector should appear in a separate window.
187      *
188      * Since: 1.0.3
189      */
190     webkit_web_inspector_signals[DETACH_WINDOW] = g_signal_new("detach-window",
191             G_TYPE_FROM_CLASS(klass),
192             (GSignalFlags)G_SIGNAL_RUN_LAST,
193             0,
194             g_signal_accumulator_true_handled,
195             NULL,
196             webkit_marshal_BOOLEAN__VOID,
197             G_TYPE_BOOLEAN , 0);
198 
199     /**
200      * WebKitWebInspector::close-window:
201      * @web_inspector: the object on which the signal is emitted
202      * @return: %TRUE if the signal has been handled
203      *
204      * Emitted when the inspector window should be closed. You can
205      * destroy the window or hide it so that it can be displayed again
206      * by handling #WebKitWebInspector::show-window later on.
207      *
208      * Notice that the inspected #WebKitWebView may no longer exist
209      * when this signal is emitted.
210      *
211      * Notice, too, that if you decide to destroy the window,
212      * #WebKitWebInspector::inspect-web-view will be emmited again, when the user
213      * inspects an element.
214      *
215      * Since: 1.0.3
216      */
217     webkit_web_inspector_signals[CLOSE_WINDOW] = g_signal_new("close-window",
218             G_TYPE_FROM_CLASS(klass),
219             (GSignalFlags)G_SIGNAL_RUN_LAST,
220             0,
221             g_signal_accumulator_true_handled,
222             NULL,
223             webkit_marshal_BOOLEAN__VOID,
224             G_TYPE_BOOLEAN , 0);
225 
226     /**
227      * WebKitWebInspector::finished:
228      * @web_inspector: the object on which the signal is emitted
229      *
230      * Emitted when the inspection is done. You should release your
231      * references on the inspector at this time. The inspected
232      * #WebKitWebView may no longer exist when this signal is emitted.
233      *
234      * Since: 1.0.3
235      */
236     webkit_web_inspector_signals[FINISHED] = g_signal_new("finished",
237             G_TYPE_FROM_CLASS(klass),
238             (GSignalFlags)G_SIGNAL_RUN_LAST,
239             0,
240             NULL,
241             NULL,
242             g_cclosure_marshal_VOID__VOID,
243             G_TYPE_NONE , 0);
244 
245     /*
246      * properties
247      */
248 
249     /**
250      * WebKitWebInspector:web-view:
251      *
252      * The Web View that renders the Web Inspector itself.
253      *
254      * Since: 1.0.3
255      */
256     g_object_class_install_property(gobject_class, PROP_WEB_VIEW,
257                                     g_param_spec_object("web-view",
258                                                         _("Web View"),
259                                                         _("The Web View that renders the Web Inspector itself"),
260                                                         WEBKIT_TYPE_WEB_VIEW,
261                                                         WEBKIT_PARAM_READABLE));
262 
263     /**
264      * WebKitWebInspector:inspected-uri:
265      *
266      * The URI that is currently being inspected.
267      *
268      * Since: 1.0.3
269      */
270     g_object_class_install_property(gobject_class, PROP_INSPECTED_URI,
271                                     g_param_spec_string("inspected-uri",
272                                                         _("Inspected URI"),
273                                                         _("The URI that is currently being inspected"),
274                                                         NULL,
275                                                         WEBKIT_PARAM_READABLE));
276 
277     /**
278     * WebKitWebInspector:javascript-profiling-enabled
279     *
280     * This is enabling JavaScript profiling in the Inspector. This means
281     * that Console.profiles will return the profiles.
282     *
283     * Since: 1.1.1
284     */
285     g_object_class_install_property(gobject_class,
286                                     PROP_JAVASCRIPT_PROFILING_ENABLED,
287                                     g_param_spec_boolean(
288                                         "javascript-profiling-enabled",
289                                         _("Enable JavaScript profiling"),
290                                         _("Profile the executed JavaScript."),
291                                         FALSE,
292                                         WEBKIT_PARAM_READWRITE));
293 
294     g_type_class_add_private(klass, sizeof(WebKitWebInspectorPrivate));
295 }
296 
webkit_web_inspector_init(WebKitWebInspector * web_inspector)297 static void webkit_web_inspector_init(WebKitWebInspector* web_inspector)
298 {
299     web_inspector->priv = WEBKIT_WEB_INSPECTOR_GET_PRIVATE(web_inspector);
300 }
301 
webkit_web_inspector_finalize(GObject * object)302 static void webkit_web_inspector_finalize(GObject* object)
303 {
304     WebKitWebInspector* web_inspector = WEBKIT_WEB_INSPECTOR(object);
305     WebKitWebInspectorPrivate* priv = web_inspector->priv;
306 
307     if (priv->inspector_view)
308         g_object_unref(priv->inspector_view);
309 
310     if (priv->inspected_uri)
311         g_free(priv->inspected_uri);
312 
313     G_OBJECT_CLASS(webkit_web_inspector_parent_class)->finalize(object);
314 }
315 
webkit_web_inspector_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)316 static void webkit_web_inspector_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
317 {
318     WebKitWebInspector* web_inspector = WEBKIT_WEB_INSPECTOR(object);
319     WebKitWebInspectorPrivate* priv = web_inspector->priv;
320 
321     switch(prop_id) {
322     case PROP_JAVASCRIPT_PROFILING_ENABLED: {
323         bool enabled = g_value_get_boolean(value);
324         WebCore::InspectorController* controller = priv->page->inspectorController();
325         if (enabled)
326             controller->enableProfiler();
327         else
328             controller->disableProfiler();
329         break;
330     }
331     default:
332         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
333         break;
334     }
335 }
336 
webkit_web_inspector_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)337 static void webkit_web_inspector_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
338 {
339     WebKitWebInspector* web_inspector = WEBKIT_WEB_INSPECTOR(object);
340     WebKitWebInspectorPrivate* priv = web_inspector->priv;
341 
342     switch (prop_id) {
343     case PROP_WEB_VIEW:
344         g_value_set_object(value, priv->inspector_view);
345         break;
346     case PROP_INSPECTED_URI:
347         g_value_set_string(value, priv->inspected_uri);
348         break;
349     case PROP_JAVASCRIPT_PROFILING_ENABLED:
350         g_value_set_boolean(value, priv->page->inspectorController()->profilerEnabled());
351         break;
352     default:
353         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
354         break;
355     }
356 }
357 
358 // internal use only
webkit_web_inspector_set_web_view(WebKitWebInspector * web_inspector,WebKitWebView * web_view)359 void webkit_web_inspector_set_web_view(WebKitWebInspector *web_inspector, WebKitWebView *web_view)
360 {
361     g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(web_inspector));
362     g_return_if_fail(WEBKIT_IS_WEB_VIEW(web_view));
363 
364     WebKitWebInspectorPrivate* priv = web_inspector->priv;
365 
366     if (priv->inspector_view)
367         g_object_unref(priv->inspector_view);
368 
369     g_object_ref(web_view);
370     priv->inspector_view = web_view;
371 }
372 
373 /**
374  * webkit_web_inspector_get_web_view:
375  *
376  * Obtains the #WebKitWebView that is used to render the
377  * inspector. The #WebKitWebView instance is created by the
378  * application, by handling the #WebKitWebInspector::inspect-web-view signal. This means
379  * that this method may return %NULL if the user hasn't inspected
380  * anything.
381  *
382  * Returns: the #WebKitWebView instance that is used to render the
383  * inspector or %NULL if it is not yet created.
384  *
385  * Since: 1.0.3
386  **/
webkit_web_inspector_get_web_view(WebKitWebInspector * web_inspector)387 WebKitWebView* webkit_web_inspector_get_web_view(WebKitWebInspector *web_inspector)
388 {
389     WebKitWebInspectorPrivate* priv = web_inspector->priv;
390 
391     return priv->inspector_view;
392 }
393 
394 // internal use only
webkit_web_inspector_set_inspected_uri(WebKitWebInspector * web_inspector,const gchar * inspected_uri)395 void webkit_web_inspector_set_inspected_uri(WebKitWebInspector* web_inspector, const gchar* inspected_uri)
396 {
397     g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(web_inspector));
398 
399     WebKitWebInspectorPrivate* priv = web_inspector->priv;
400 
401     g_free(priv->inspected_uri);
402     priv->inspected_uri = g_strdup(inspected_uri);
403 }
404 
405 /**
406  * webkit_web_inspector_get_inspected_uri:
407  *
408  * Obtains the URI that is currently being inspected.
409  *
410  * Returns: a pointer to the URI as an internally allocated string; it
411  * should not be freed, modified or stored.
412  *
413  * Since: 1.0.3
414  **/
webkit_web_inspector_get_inspected_uri(WebKitWebInspector * web_inspector)415 const gchar* webkit_web_inspector_get_inspected_uri(WebKitWebInspector *web_inspector)
416 {
417     WebKitWebInspectorPrivate* priv = web_inspector->priv;
418 
419     return priv->inspected_uri;
420 }
421 
422 void
webkit_web_inspector_set_inspector_client(WebKitWebInspector * web_inspector,WebCore::Page * page)423 webkit_web_inspector_set_inspector_client(WebKitWebInspector* web_inspector, WebCore::Page* page)
424 {
425     WebKitWebInspectorPrivate* priv = web_inspector->priv;
426 
427     priv->page = page;
428 }
429