Home | History | Annotate | Download | only in webkit
      1 /*
      2  * Copyright (C) 2008 Gustavo Noronha Silva
      3  * Copyright (C) 2008, 2009 Holger Hans Peter Freyther
      4  * Copyright (C) 2009 Collabora Ltd.
      5  *
      6  * This library is free software; you can redistribute it and/or
      7  * modify it under the terms of the GNU Library General Public
      8  * License as published by the Free Software Foundation; either
      9  * version 2 of the License, or (at your option) any later version.
     10  *
     11  * This library is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14  * Library General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU Library General Public License
     17  * along with this library; see the file COPYING.LIB.  If not, write to
     18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19  * Boston, MA 02110-1301, USA.
     20  */
     21 
     22 #include "config.h"
     23 #include "webkitwebinspector.h"
     24 
     25 #include "DumpRenderTreeSupportGtk.h"
     26 #include "FocusController.h"
     27 #include "Frame.h"
     28 #include "HitTestRequest.h"
     29 #include "HitTestResult.h"
     30 #include "InspectorClientGtk.h"
     31 #include "InspectorController.h"
     32 #include "InspectorInstrumentation.h"
     33 #include "IntPoint.h"
     34 #include "Page.h"
     35 #include "RenderLayer.h"
     36 #include "RenderView.h"
     37 #include "webkit/WebKitDOMNodePrivate.h"
     38 #include "webkitglobalsprivate.h"
     39 #include "webkitmarshal.h"
     40 #include "webkitwebinspectorprivate.h"
     41 #include <glib/gi18n-lib.h>
     42 
     43 /**
     44  * SECTION:webkitwebinspector
     45  * @short_description: Access to the WebKit Inspector
     46  *
     47  * The WebKit Inspector is a graphical tool to inspect and change
     48  * the content of a #WebKitWebView. It also includes an interactive
     49  * JavaScriptDebugger. Using this class one can get a GtkWidget which
     50  * can be embedded into an application to show the inspector.
     51  *
     52  * The inspector is available when the #WebKitWebSettings of the
     53  * #WebKitWebView has set the #WebKitWebSettings:enable-developer-extras
     54  * to true otherwise no inspector is available.
     55  *
     56  * <informalexample><programlisting>
     57  * /<!-- -->* Enable the developer extras *<!-- -->/
     58  * WebKitWebSettings *setting = webkit_web_view_get_settings (WEBKIT_WEB_VIEW(my_webview));
     59  * g_object_set (G_OBJECT(settings), "enable-developer-extras", TRUE, NULL);
     60  *
     61  * /<!-- -->* load some data or reload to be able to inspect the page*<!-- -->/
     62  * webkit_web_view_open (WEBKIT_WEB_VIEW(my_webview), "http://www.gnome.org");
     63  *
     64  * /<!-- -->* Embed the inspector somewhere *<!-- -->/
     65  * WebKitWebInspector *inspector = webkit_web_view_get_inspector (WEBKIT_WEB_VIEW(my_webview));
     66  * g_signal_connect (G_OBJECT (inspector), "inspect-web-view", G_CALLBACK(create_gtk_window_around_it), NULL);
     67  * g_signal_connect (G_OBJECT (inspector), "show-window", G_CALLBACK(show_inpector_window), NULL));
     68  * g_signal_connect (G_OBJECT (inspector), "notify::inspected-uri", G_CALLBACK(inspected_uri_changed_do_stuff), NULL);
     69  * </programlisting></informalexample>
     70  */
     71 
     72 using namespace WebKit;
     73 using namespace WebCore;
     74 
     75 enum {
     76     INSPECT_WEB_VIEW,
     77     SHOW_WINDOW,
     78     ATTACH_WINDOW,
     79     DETACH_WINDOW,
     80     CLOSE_WINDOW,
     81     FINISHED,
     82     LAST_SIGNAL
     83 };
     84 
     85 static guint webkit_web_inspector_signals[LAST_SIGNAL] = { 0, };
     86 
     87 enum {
     88     PROP_0,
     89 
     90     PROP_WEB_VIEW,
     91     PROP_INSPECTED_URI,
     92     PROP_JAVASCRIPT_PROFILING_ENABLED,
     93     PROP_TIMELINE_PROFILING_ENABLED
     94 };
     95 
     96 G_DEFINE_TYPE(WebKitWebInspector, webkit_web_inspector, G_TYPE_OBJECT)
     97 
     98 struct _WebKitWebInspectorPrivate {
     99     WebCore::Page* page;
    100     WebKitWebView* inspector_view;
    101     gchar* inspected_uri;
    102 };
    103 
    104 static void webkit_web_inspector_finalize(GObject* object);
    105 
    106 static void webkit_web_inspector_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec);
    107 
    108 static void webkit_web_inspector_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec);
    109 
    110 static gboolean webkit_inspect_web_view_request_handled(GSignalInvocationHint* ihint, GValue* returnAccu, const GValue* handlerReturn, gpointer dummy)
    111 {
    112     gboolean continueEmission = TRUE;
    113     gpointer newWebView = g_value_get_object(handlerReturn);
    114     g_value_set_object(returnAccu, newWebView);
    115 
    116     if (newWebView)
    117         continueEmission = FALSE;
    118 
    119     return continueEmission;
    120 }
    121 
    122 static void webkit_web_inspector_class_init(WebKitWebInspectorClass* klass)
    123 {
    124     GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
    125     gobject_class->finalize = webkit_web_inspector_finalize;
    126     gobject_class->set_property = webkit_web_inspector_set_property;
    127     gobject_class->get_property = webkit_web_inspector_get_property;
    128 
    129     /**
    130      * WebKitWebInspector::inspect-web-view:
    131      * @web_inspector: the object on which the signal is emitted
    132      * @web_view: the #WebKitWebView which will be inspected
    133      *
    134      * Emitted when the user activates the 'inspect' context menu item
    135      * to inspect a web view. The application which is interested in
    136      * the inspector should create a window, or otherwise add the
    137      * #WebKitWebView it creates to an existing window.
    138      *
    139      * You don't need to handle the reference count of the
    140      * #WebKitWebView instance you create; the widget to which you add
    141      * it will do that.
    142      *
    143      * Return value: (transfer none): a newly allocated #WebKitWebView or %NULL
    144      *
    145      * Since: 1.0.3
    146      */
    147     webkit_web_inspector_signals[INSPECT_WEB_VIEW] = g_signal_new("inspect-web-view",
    148             G_TYPE_FROM_CLASS(klass),
    149             (GSignalFlags)G_SIGNAL_RUN_LAST,
    150             0,
    151             webkit_inspect_web_view_request_handled,
    152             NULL,
    153             webkit_marshal_OBJECT__OBJECT,
    154             WEBKIT_TYPE_WEB_VIEW , 1,
    155             WEBKIT_TYPE_WEB_VIEW);
    156 
    157     /**
    158      * WebKitWebInspector::show-window:
    159      * @web_inspector: the object on which the signal is emitted
    160      * @return: %TRUE if the signal has been handled
    161      *
    162      * Emitted when the inspector window should be displayed. Notice
    163      * that the window must have been created already by handling
    164      * #WebKitWebInspector::inspect-web-view.
    165      *
    166      * Since: 1.0.3
    167      */
    168     webkit_web_inspector_signals[SHOW_WINDOW] = g_signal_new("show-window",
    169             G_TYPE_FROM_CLASS(klass),
    170             (GSignalFlags)G_SIGNAL_RUN_LAST,
    171             0,
    172             g_signal_accumulator_true_handled,
    173             NULL,
    174             webkit_marshal_BOOLEAN__VOID,
    175             G_TYPE_BOOLEAN , 0);
    176 
    177     /**
    178      * WebKitWebInspector::attach-window:
    179      * @web_inspector: the object on which the signal is emitted
    180      * @return: %TRUE if the signal has been handled
    181      *
    182      * Emitted when the inspector should appear at the same window as
    183      * the #WebKitWebView being inspected.
    184      *
    185      * Since: 1.0.3
    186      */
    187     webkit_web_inspector_signals[ATTACH_WINDOW] = g_signal_new("attach-window",
    188             G_TYPE_FROM_CLASS(klass),
    189             (GSignalFlags)G_SIGNAL_RUN_LAST,
    190             0,
    191             g_signal_accumulator_true_handled,
    192             NULL,
    193             webkit_marshal_BOOLEAN__VOID,
    194             G_TYPE_BOOLEAN , 0);
    195 
    196     /**
    197      * WebKitWebInspector::detach-window:
    198      * @web_inspector: the object on which the signal is emitted
    199      * @return: %TRUE if the signal has been handled
    200      *
    201      * Emitted when the inspector should appear in a separate window.
    202      *
    203      * Since: 1.0.3
    204      */
    205     webkit_web_inspector_signals[DETACH_WINDOW] = g_signal_new("detach-window",
    206             G_TYPE_FROM_CLASS(klass),
    207             (GSignalFlags)G_SIGNAL_RUN_LAST,
    208             0,
    209             g_signal_accumulator_true_handled,
    210             NULL,
    211             webkit_marshal_BOOLEAN__VOID,
    212             G_TYPE_BOOLEAN , 0);
    213 
    214     /**
    215      * WebKitWebInspector::close-window:
    216      * @web_inspector: the object on which the signal is emitted
    217      * @return: %TRUE if the signal has been handled
    218      *
    219      * Emitted when the inspector window should be closed. You can
    220      * destroy the window or hide it so that it can be displayed again
    221      * by handling #WebKitWebInspector::show-window later on.
    222      *
    223      * Notice that the inspected #WebKitWebView may no longer exist
    224      * when this signal is emitted.
    225      *
    226      * Notice, too, that if you decide to destroy the window,
    227      * #WebKitWebInspector::inspect-web-view will be emmited again, when the user
    228      * inspects an element.
    229      *
    230      * Since: 1.0.3
    231      */
    232     webkit_web_inspector_signals[CLOSE_WINDOW] = g_signal_new("close-window",
    233             G_TYPE_FROM_CLASS(klass),
    234             (GSignalFlags)G_SIGNAL_RUN_LAST,
    235             0,
    236             g_signal_accumulator_true_handled,
    237             NULL,
    238             webkit_marshal_BOOLEAN__VOID,
    239             G_TYPE_BOOLEAN , 0);
    240 
    241     /**
    242      * WebKitWebInspector::finished:
    243      * @web_inspector: the object on which the signal is emitted
    244      *
    245      * Emitted when the inspection is done. You should release your
    246      * references on the inspector at this time. The inspected
    247      * #WebKitWebView may no longer exist when this signal is emitted.
    248      *
    249      * Since: 1.0.3
    250      */
    251     webkit_web_inspector_signals[FINISHED] = g_signal_new("finished",
    252             G_TYPE_FROM_CLASS(klass),
    253             (GSignalFlags)G_SIGNAL_RUN_LAST,
    254             0,
    255             NULL,
    256             NULL,
    257             g_cclosure_marshal_VOID__VOID,
    258             G_TYPE_NONE , 0);
    259 
    260     /*
    261      * properties
    262      */
    263 
    264     /**
    265      * WebKitWebInspector:web-view:
    266      *
    267      * The Web View that renders the Web Inspector itself.
    268      *
    269      * Since: 1.0.3
    270      */
    271     g_object_class_install_property(gobject_class, PROP_WEB_VIEW,
    272                                     g_param_spec_object("web-view",
    273                                                         _("Web View"),
    274                                                         _("The Web View that renders the Web Inspector itself"),
    275                                                         WEBKIT_TYPE_WEB_VIEW,
    276                                                         WEBKIT_PARAM_READABLE));
    277 
    278     /**
    279      * WebKitWebInspector:inspected-uri:
    280      *
    281      * The URI that is currently being inspected.
    282      *
    283      * Since: 1.0.3
    284      */
    285     g_object_class_install_property(gobject_class, PROP_INSPECTED_URI,
    286                                     g_param_spec_string("inspected-uri",
    287                                                         _("Inspected URI"),
    288                                                         _("The URI that is currently being inspected"),
    289                                                         NULL,
    290                                                         WEBKIT_PARAM_READABLE));
    291 
    292     /**
    293     * WebKitWebInspector:javascript-profiling-enabled
    294     *
    295     * This is enabling JavaScript profiling in the Inspector. This means
    296     * that Console.profiles will return the profiles.
    297     *
    298     * Since: 1.1.1
    299     */
    300     g_object_class_install_property(gobject_class,
    301                                     PROP_JAVASCRIPT_PROFILING_ENABLED,
    302                                     g_param_spec_boolean(
    303                                         "javascript-profiling-enabled",
    304                                         _("Enable JavaScript profiling"),
    305                                         _("Profile the executed JavaScript."),
    306                                         FALSE,
    307                                         WEBKIT_PARAM_READWRITE));
    308 
    309     /**
    310     * WebKitWebInspector:timeline-profiling-enabled
    311     *
    312     * This is enabling Timeline profiling in the Inspector.
    313     *
    314     * Since: 1.1.17
    315     */
    316     g_object_class_install_property(gobject_class,
    317                                     PROP_TIMELINE_PROFILING_ENABLED,
    318                                     g_param_spec_boolean(
    319                                         "timeline-profiling-enabled",
    320                                         _("Enable Timeline profiling"),
    321                                         _("Profile the WebCore instrumentation."),
    322                                         FALSE,
    323                                         WEBKIT_PARAM_READWRITE));
    324 
    325     g_type_class_add_private(klass, sizeof(WebKitWebInspectorPrivate));
    326 }
    327 
    328 static void webkit_web_inspector_init(WebKitWebInspector* web_inspector)
    329 {
    330     web_inspector->priv = G_TYPE_INSTANCE_GET_PRIVATE(web_inspector, WEBKIT_TYPE_WEB_INSPECTOR, WebKitWebInspectorPrivate);
    331 }
    332 
    333 static void webkit_web_inspector_finalize(GObject* object)
    334 {
    335     WebKitWebInspector* web_inspector = WEBKIT_WEB_INSPECTOR(object);
    336     WebKitWebInspectorPrivate* priv = web_inspector->priv;
    337 
    338     if (priv->inspector_view)
    339         g_object_unref(priv->inspector_view);
    340 
    341     if (priv->inspected_uri)
    342         g_free(priv->inspected_uri);
    343 
    344     G_OBJECT_CLASS(webkit_web_inspector_parent_class)->finalize(object);
    345 }
    346 
    347 static void webkit_web_inspector_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
    348 {
    349     WebKitWebInspector* web_inspector = WEBKIT_WEB_INSPECTOR(object);
    350     WebKitWebInspectorPrivate* priv = web_inspector->priv;
    351 
    352     switch(prop_id) {
    353     case PROP_JAVASCRIPT_PROFILING_ENABLED: {
    354 #if ENABLE(JAVASCRIPT_DEBUGGER)
    355         bool enabled = g_value_get_boolean(value);
    356         WebCore::InspectorController* controller = priv->page->inspectorController();
    357         if (enabled)
    358             controller->enableProfiler();
    359         else
    360             controller->disableProfiler();
    361 #else
    362         g_message("PROP_JAVASCRIPT_PROFILING_ENABLED is not work because of the javascript debugger is disabled\n");
    363 #endif
    364         break;
    365     }
    366     case PROP_TIMELINE_PROFILING_ENABLED: {
    367         bool enabled = g_value_get_boolean(value);
    368         WebCore::InspectorController* controller = priv->page->inspectorController();
    369         if (enabled)
    370             controller->startTimelineProfiler();
    371         else
    372             controller->stopTimelineProfiler();
    373         break;
    374     }
    375     default:
    376         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    377         break;
    378     }
    379 }
    380 
    381 static void webkit_web_inspector_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
    382 {
    383     WebKitWebInspector* web_inspector = WEBKIT_WEB_INSPECTOR(object);
    384     WebKitWebInspectorPrivate* priv = web_inspector->priv;
    385 
    386     switch (prop_id) {
    387     case PROP_WEB_VIEW:
    388         g_value_set_object(value, priv->inspector_view);
    389         break;
    390     case PROP_INSPECTED_URI:
    391         g_value_set_string(value, priv->inspected_uri);
    392         break;
    393     case PROP_JAVASCRIPT_PROFILING_ENABLED:
    394 #if ENABLE(JAVASCRIPT_DEBUGGER)
    395         g_value_set_boolean(value, priv->page->inspectorController()->profilerEnabled());
    396 #else
    397         g_message("PROP_JAVASCRIPT_PROFILING_ENABLED is not work because of the javascript debugger is disabled\n");
    398 #endif
    399         break;
    400     case PROP_TIMELINE_PROFILING_ENABLED:
    401         g_value_set_boolean(value, priv->page->inspectorController()->timelineProfilerEnabled());
    402         break;
    403     default:
    404         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    405         break;
    406     }
    407 }
    408 
    409 // internal use only
    410 void webkit_web_inspector_set_web_view(WebKitWebInspector *web_inspector, WebKitWebView *web_view)
    411 {
    412     g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(web_inspector));
    413     g_return_if_fail(WEBKIT_IS_WEB_VIEW(web_view));
    414 
    415     WebKitWebInspectorPrivate* priv = web_inspector->priv;
    416 
    417     if (priv->inspector_view)
    418         g_object_unref(priv->inspector_view);
    419 
    420     g_object_ref(web_view);
    421     priv->inspector_view = web_view;
    422 }
    423 
    424 /**
    425  * webkit_web_inspector_get_web_view:
    426  *
    427  * Obtains the #WebKitWebView that is used to render the
    428  * inspector. The #WebKitWebView instance is created by the
    429  * application, by handling the #WebKitWebInspector::inspect-web-view signal. This means
    430  * that this method may return %NULL if the user hasn't inspected
    431  * anything.
    432  *
    433  * Returns: (transfer none): the #WebKitWebView instance that is used
    434  * to render the inspector or %NULL if it is not yet created.
    435  *
    436  * Since: 1.0.3
    437  **/
    438 WebKitWebView* webkit_web_inspector_get_web_view(WebKitWebInspector *web_inspector)
    439 {
    440     WebKitWebInspectorPrivate* priv = web_inspector->priv;
    441 
    442     return priv->inspector_view;
    443 }
    444 
    445 // internal use only
    446 void webkit_web_inspector_set_inspected_uri(WebKitWebInspector* web_inspector, const gchar* inspected_uri)
    447 {
    448     g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(web_inspector));
    449 
    450     WebKitWebInspectorPrivate* priv = web_inspector->priv;
    451 
    452     g_free(priv->inspected_uri);
    453     priv->inspected_uri = g_strdup(inspected_uri);
    454 }
    455 
    456 /**
    457  * webkit_web_inspector_get_inspected_uri:
    458  *
    459  * Obtains the URI that is currently being inspected.
    460  *
    461  * Returns: a pointer to the URI as an internally allocated string; it
    462  * should not be freed, modified or stored.
    463  *
    464  * Since: 1.0.3
    465  **/
    466 const gchar* webkit_web_inspector_get_inspected_uri(WebKitWebInspector *web_inspector)
    467 {
    468     WebKitWebInspectorPrivate* priv = web_inspector->priv;
    469 
    470     return priv->inspected_uri;
    471 }
    472 
    473 void
    474 webkit_web_inspector_set_inspector_client(WebKitWebInspector* web_inspector, WebCore::Page* page)
    475 {
    476     WebKitWebInspectorPrivate* priv = web_inspector->priv;
    477 
    478     priv->page = page;
    479 }
    480 
    481 /**
    482  * webkit_web_inspector_show:
    483  * @webInspector: the #WebKitWebInspector that will be shown
    484  *
    485  * Causes the Web Inspector to be shown.
    486  *
    487  * Since: 1.1.17
    488  */
    489 void webkit_web_inspector_show(WebKitWebInspector* webInspector)
    490 {
    491     g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(webInspector));
    492 
    493     WebKitWebInspectorPrivate* priv = webInspector->priv;
    494 
    495     Frame* frame = priv->page->focusController()->focusedOrMainFrame();
    496     FrameView* view = frame->view();
    497 
    498     if (!view)
    499         return;
    500 
    501     priv->page->inspectorController()->show();
    502 }
    503 
    504 /**
    505  * webkit_web_inspector_inspect_node:
    506  * @web_inspector: the #WebKitWebInspector that will do the inspection
    507  * @node: the #WebKitDOMNode to inspect
    508  *
    509  * Causes the Web Inspector to inspect the given node.
    510  *
    511  * Since: 1.3.7
    512  */
    513 void webkit_web_inspector_inspect_node(WebKitWebInspector* webInspector, WebKitDOMNode* node)
    514 {
    515     g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(webInspector));
    516     g_return_if_fail(WEBKIT_DOM_IS_NODE(node));
    517 
    518     webInspector->priv->page->inspectorController()->inspect(core(node));
    519 }
    520 
    521 /**
    522  * webkit_web_inspector_inspect_coordinates:
    523  * @web_inspector: the #WebKitWebInspector that will do the inspection
    524  * @x: the X coordinate of the node to be inspected
    525  * @y: the Y coordinate of the node to be inspected
    526  *
    527  * Causes the Web Inspector to inspect the node that is located at the
    528  * given coordinates of the widget. The coordinates should be relative
    529  * to the #WebKitWebView widget, not to the scrollable content, and
    530  * may be obtained from a #GdkEvent directly.
    531  *
    532  * This means @x, and @y being zero doesn't guarantee you will hit the
    533  * left-most top corner of the content, since the contents may have
    534  * been scrolled.
    535  *
    536  * Since: 1.1.17
    537  */
    538 void webkit_web_inspector_inspect_coordinates(WebKitWebInspector* webInspector, gdouble x, gdouble y)
    539 {
    540     g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(webInspector));
    541     g_return_if_fail(x >= 0 && y >= 0);
    542 
    543     WebKitWebInspectorPrivate* priv = webInspector->priv;
    544 
    545     Frame* frame = priv->page->focusController()->focusedOrMainFrame();
    546     FrameView* view = frame->view();
    547 
    548     if (!view)
    549         return;
    550 
    551     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
    552     IntPoint documentPoint = view->windowToContents(IntPoint(static_cast<int>(x), static_cast<int>(y)));
    553     HitTestResult result(documentPoint);
    554 
    555     frame->contentRenderer()->layer()->hitTest(request, result);
    556     priv->page->inspectorController()->inspect(result.innerNonSharedNode());
    557 }
    558 
    559 /**
    560  * webkit_web_inspector_close:
    561  * @webInspector: the #WebKitWebInspector that will be closed
    562  *
    563  * Causes the Web Inspector to be closed.
    564  *
    565  * Since: 1.1.17
    566  */
    567 void webkit_web_inspector_close(WebKitWebInspector* webInspector)
    568 {
    569     g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(webInspector));
    570 
    571     WebKitWebInspectorPrivate* priv = webInspector->priv;
    572     priv->page->inspectorController()->close();
    573 }
    574 
    575 void webkit_web_inspector_execute_script(WebKitWebInspector* webInspector, long callId, const gchar* script)
    576 {
    577     g_return_if_fail(WEBKIT_IS_WEB_INSPECTOR(webInspector));
    578     g_return_if_fail(script);
    579 
    580     WebKitWebInspectorPrivate* priv = webInspector->priv;
    581     priv->page->inspectorController()->evaluateForTestInFrontend(callId, script);
    582 }
    583 
    584 #ifdef HAVE_GSETTINGS
    585 static bool isSchemaAvailable(const char* schemaID)
    586 {
    587     const char* const* availableSchemas = g_settings_list_schemas();
    588     char* const* iter = const_cast<char* const*>(availableSchemas);
    589 
    590     while (*iter) {
    591         if (g_str_equal(schemaID, *iter))
    592             return true;
    593         iter++;
    594     }
    595 
    596     return false;
    597 }
    598 
    599 GSettings* inspectorGSettings()
    600 {
    601     static GSettings* settings = 0;
    602     if (settings)
    603         return settings;
    604 
    605     // Unfortunately GSettings will abort the process execution if the schema is not
    606     // installed, which is the case for when running tests, or even the introspection dump
    607     // at build time, so check if we have the schema before trying to initialize it.
    608     const gchar* schemaID = "org.webkitgtk-"WEBKITGTK_API_VERSION_STRING".inspector";
    609     if (!isSchemaAvailable(schemaID)) {
    610 
    611         // This warning is very common on the build bots, which hides valid warnings.
    612         // Skip printing it if we are running inside DumpRenderTree.
    613         if (!DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled())
    614             g_warning("GSettings schema not found - settings will not be used or saved.");
    615         return 0;
    616     }
    617 
    618     settings = g_settings_new(schemaID);
    619     return settings;
    620 }
    621 #endif
    622