~noskcaj/ubuntu/wily/epiphany-browser/merge2

« back to all changes in this revision

Viewing changes to src/ephy-python-extension.c

Tags: upstream-2.28.0
ImportĀ upstreamĀ versionĀ 2.28.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright Ā© 2003 Marco Pesenti Gritti
3
 
 *  Copyright Ā© 2003 Christian Persch
4
 
 *  Copyright Ā© 2004, 2005 Adam Hooper
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; either version 2, or (at your option)
9
 
 *  any later version.
10
 
 *
11
 
 *  This program 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
14
 
 *  GNU General Public License for more details.
15
 
 *
16
 
 *  You should have received a copy of the GNU General Public License
17
 
 *  along with this program; if not, write to the Free Software
18
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
 
 *
20
 
 *  $Id$
21
 
 */
22
 
 
23
 
#include "Python.h"
24
 
 
25
 
#include "config.h"
26
 
 
27
 
#include "ephy-python-extension.h"
28
 
#include "ephy-python.h"
29
 
 
30
 
#define NO_IMPORT_PYGOBJECT
31
 
#include <pygobject.h>
32
 
 
33
 
#include "ephy-extension.h"
34
 
#include "ephy-window.h"
35
 
#include "ephy-file-helpers.h"
36
 
#include "ephy-debug.h"
37
 
 
38
 
static void ephy_python_extension_iface_init (EphyExtensionIface *iface);
39
 
 
40
 
#define EPHY_PYTHON_EXTENSION_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_PYTHON_EXTENSION, EphyPythonExtensionPrivate))
41
 
 
42
 
struct _EphyPythonExtensionPrivate
43
 
{
44
 
        char *filename;
45
 
        PyObject *module;
46
 
};
47
 
 
48
 
enum
49
 
{
50
 
        PROP_0,
51
 
        PROP_FILENAME
52
 
};
53
 
 
54
 
static int
55
 
set_python_search_path (const char *filename)
56
 
{
57
 
        char *dirname;
58
 
        char *dot_dir;
59
 
        int ret = 2;
60
 
        PyObject *sys_path;
61
 
        PyObject *pValue;
62
 
 
63
 
        sys_path = PySys_GetObject ("path");
64
 
 
65
 
        /* Systems extensions dir */
66
 
        pValue = PyString_FromString (EXTENSIONS_DIR);
67
 
        PyList_Insert (sys_path, 0, pValue);
68
 
        Py_DECREF (pValue);
69
 
 
70
 
        /* Home dir */
71
 
        dot_dir = g_strconcat (ephy_dot_dir (), "/extensions", NULL);
72
 
        pValue = PyString_FromString (dot_dir);
73
 
        PyList_Insert (sys_path, 0, pValue);
74
 
        Py_DECREF (pValue);
75
 
        g_free (dot_dir);
76
 
 
77
 
        /* Absolute path specified in .xml file */
78
 
        dirname = g_path_get_dirname (filename);
79
 
        if (g_path_is_absolute (dirname))
80
 
        {
81
 
                pValue = PyString_FromString (dirname);
82
 
                PyList_Insert (sys_path, 0, pValue);
83
 
                Py_DECREF (pValue);
84
 
                ret++;
85
 
        }
86
 
        g_free (dirname);
87
 
 
88
 
        return ret;
89
 
}
90
 
 
91
 
static void
92
 
unset_python_search_path (int num_dirs)
93
 
{
94
 
        PyObject *sys_path = PySys_GetObject ("path");
95
 
 
96
 
        PySequence_DelSlice (sys_path, 0, num_dirs);
97
 
}
98
 
 
99
 
static void
100
 
ephy_python_extension_init (EphyPythonExtension *extension)
101
 
{
102
 
        LOG ("EphyPythonExtension initialising");
103
 
 
104
 
        extension->priv = EPHY_PYTHON_EXTENSION_GET_PRIVATE (extension);
105
 
}
106
 
 
107
 
static void
108
 
call_python_func (EphyExtension *extension,
109
 
                  const char *func_name,
110
 
                  EphyWindow *window,
111
 
                  EphyEmbed *embed) /* HACK: tab may be NULL */
112
 
{
113
 
        PyObject *pDict, *pFunc;
114
 
        PyObject *pArgs, *pValue, *pEmbed = NULL, *pWindow;
115
 
        EphyPythonExtension *py_ext;
116
 
        
117
 
        py_ext = EPHY_PYTHON_EXTENSION (extension);
118
 
 
119
 
        /* Happens if the module load fails, e.g. python couldn't
120
 
         * parse it, so be quiet about it, we will have already warned */
121
 
        if (py_ext->priv->module == NULL)
122
 
        {
123
 
                return;
124
 
        }
125
 
 
126
 
        pDict = PyModule_GetDict (py_ext->priv->module);
127
 
        pFunc = PyDict_GetItemString (pDict, func_name);
128
 
 
129
 
        if (pFunc && PyCallable_Check (pFunc))
130
 
        {
131
 
                pArgs = PyTuple_New (embed == NULL ? 1 : 2);
132
 
 
133
 
                pWindow = pygobject_new (G_OBJECT (window));
134
 
                PyTuple_SetItem (pArgs, 0, pWindow);
135
 
 
136
 
                if (embed != NULL)
137
 
                {
138
 
                        pEmbed = pygobject_new (G_OBJECT (embed));
139
 
                        PyTuple_SetItem (pArgs, 1, pEmbed);
140
 
                }
141
 
 
142
 
                pValue = PyObject_CallObject (pFunc, pArgs);
143
 
                if (pValue == NULL)
144
 
                {
145
 
                        PyErr_Print ();
146
 
                        PyErr_Clear ();
147
 
                        g_warning ("Python code for '%s' failed to execute",
148
 
                                   func_name);
149
 
                }
150
 
                Py_XDECREF (pValue);
151
 
                Py_DECREF (pArgs);
152
 
        }
153
 
        else
154
 
        {
155
 
                if (PyErr_Occurred ())
156
 
                {
157
 
                        PyErr_Print ();
158
 
                        PyErr_Clear ();
159
 
                }
160
 
        }
161
 
}
162
 
 
163
 
static void
164
 
impl_attach_tab (EphyExtension *extension,
165
 
                 EphyWindow *window,
166
 
                 EphyEmbed *embed)
167
 
{
168
 
        call_python_func (extension, "attach_tab", window, embed);
169
 
}
170
 
 
171
 
static void
172
 
impl_detach_tab (EphyExtension *extension,
173
 
                 EphyWindow *window,
174
 
                 EphyEmbed *embed)
175
 
{
176
 
        call_python_func (extension, "detach_tab", window, embed);
177
 
 
178
 
        ephy_python_schedule_gc ();
179
 
}
180
 
 
181
 
static void
182
 
impl_attach_window (EphyExtension *extension,
183
 
                    EphyWindow *window)
184
 
{
185
 
        call_python_func (extension, "attach_window", window, NULL);
186
 
}
187
 
 
188
 
static void
189
 
impl_detach_window (EphyExtension *extension,
190
 
                    EphyWindow *window)
191
 
{
192
 
        call_python_func (extension, "detach_window", window, NULL);
193
 
 
194
 
        ephy_python_schedule_gc ();
195
 
}
196
 
 
197
 
static void
198
 
ephy_python_extension_iface_init (EphyExtensionIface *iface)
199
 
{
200
 
        iface->attach_tab = impl_attach_tab;
201
 
        iface->detach_tab = impl_detach_tab;
202
 
        iface->attach_window = impl_attach_window;
203
 
        iface->detach_window = impl_detach_window;
204
 
}
205
 
 
206
 
G_DEFINE_TYPE_WITH_CODE (EphyPythonExtension, ephy_python_extension, G_TYPE_OBJECT,
207
 
                         G_IMPLEMENT_INTERFACE (EPHY_TYPE_EXTENSION,
208
 
                                                ephy_python_extension_iface_init))
209
 
 
210
 
static GObject *
211
 
ephy_python_extension_constructor (GType type,
212
 
                                   guint n_construct_properties,
213
 
                                   GObjectConstructParam *construct_params)
214
 
{
215
 
        GObject *object;
216
 
        EphyPythonExtension *ext;
217
 
        char *module_name;      /* filename minus optional ".py" */
218
 
                                /* Note: could equally be a directory */
219
 
        PyObject *pModules, *pModule, *pReload;
220
 
                          
221
 
        int num_temp_paths;
222
 
 
223
 
        object = G_OBJECT_CLASS (ephy_python_extension_parent_class)->constructor (type,
224
 
                                                                                   n_construct_properties,
225
 
                                                                                   construct_params);
226
 
 
227
 
        ext = EPHY_PYTHON_EXTENSION (object);
228
 
 
229
 
        module_name = g_path_get_basename (ext->priv->filename);
230
 
 
231
 
        num_temp_paths = set_python_search_path (ext->priv->filename);
232
 
 
233
 
        pModules = PySys_GetObject ("modules");
234
 
        g_assert (pModules != NULL);
235
 
 
236
 
        pModule = PyDict_GetItemString (pModules, module_name);
237
 
 
238
 
        if (pModule == NULL)
239
 
        {
240
 
                pModule = PyImport_ImportModule (module_name);
241
 
 
242
 
                if (pModule == NULL)
243
 
                {
244
 
                        PyErr_Print ();
245
 
                        PyErr_Clear ();
246
 
                        g_warning ("Could not initialize Python module '%s'",
247
 
                                   module_name);
248
 
                }
249
 
        }
250
 
        else
251
 
        {
252
 
                pReload = PyImport_ReloadModule (pModule);
253
 
 
254
 
                if (pReload == NULL)
255
 
                {
256
 
                        PyErr_Print ();
257
 
                        PyErr_Clear ();
258
 
                        g_warning ("Could not reload Python module '%s'\n"
259
 
                                   "Falling back to previous version",
260
 
                                   module_name);
261
 
                }
262
 
                else
263
 
                {
264
 
                        Py_DECREF (pReload);
265
 
                }
266
 
        }
267
 
 
268
 
        unset_python_search_path (num_temp_paths);
269
 
 
270
 
        ext->priv->module = pModule;
271
 
 
272
 
        g_free (module_name);
273
 
 
274
 
        return object;
275
 
}
276
 
 
277
 
static void
278
 
ephy_python_extension_finalize (GObject *object)
279
 
{
280
 
        EphyPythonExtension *extension =
281
 
                        EPHY_PYTHON_EXTENSION (object);
282
 
 
283
 
        LOG ("EphyPythonExtension finalizing");
284
 
 
285
 
        g_free (extension->priv->filename);
286
 
        Py_XDECREF (extension->priv->module);
287
 
 
288
 
        G_OBJECT_CLASS (ephy_python_extension_parent_class)->finalize (object);
289
 
}
290
 
 
291
 
static void
292
 
ephy_python_extension_get_property (GObject *object,
293
 
                                    guint prop_id,
294
 
                                    GValue *value,
295
 
                                    GParamSpec *pspec)
296
 
{
297
 
        /* no readable properties */
298
 
        g_return_if_reached ();
299
 
}
300
 
 
301
 
static void
302
 
ephy_python_extension_set_property (GObject *object,
303
 
                                    guint prop_id,
304
 
                                    const GValue *value,
305
 
                                    GParamSpec *pspec)
306
 
{
307
 
        EphyPythonExtension *ext = EPHY_PYTHON_EXTENSION (object);
308
 
 
309
 
        switch (prop_id)
310
 
        {
311
 
                case PROP_FILENAME:
312
 
                        ext->priv->filename = g_value_dup_string (value);
313
 
                        break;
314
 
                default:
315
 
                        g_return_if_reached ();
316
 
        }
317
 
}
318
 
 
319
 
static void
320
 
ephy_python_extension_class_init (EphyPythonExtensionClass *klass)
321
 
{
322
 
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
323
 
 
324
 
        object_class->finalize = ephy_python_extension_finalize;
325
 
        object_class->constructor = ephy_python_extension_constructor;
326
 
        object_class->get_property = ephy_python_extension_get_property;
327
 
        object_class->set_property = ephy_python_extension_set_property;
328
 
 
329
 
        g_object_class_install_property
330
 
                        (object_class,
331
 
                         PROP_FILENAME,
332
 
                         g_param_spec_string ("filename",
333
 
                                              "Filename",
334
 
                                              "Filename",
335
 
                                              NULL,
336
 
                                              G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_CONSTRUCT_ONLY));
337
 
 
338
 
        g_type_class_add_private (object_class, sizeof (EphyPythonExtensionPrivate));
339
 
}
340