2
2
* npw-wrapper.c - Host Mozilla plugin (loads the actual viewer)
4
* nspluginwrapper (C) 2005-2007 Gwenole Beauchesne
4
* nspluginwrapper (C) 2005-2008 Gwenole Beauchesne
6
6
* This program is free software; you can redistribute it and/or modify
7
7
* it under the terms of the GNU General Public License as published by
13
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
14
* GNU General Public License for more details.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
* You should have received a copy of the GNU General Public License along
17
* with this program; if not, write to the Free Software Foundation, Inc.,
18
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
21
#define _GNU_SOURCE 1 /* RTLD_DEFAULT */
22
22
#include "sysdeps.h"
25
26
#include <stdlib.h>
26
27
#include <string.h>
102
107
static void plugin_init(int is_NP_Initialize);
103
108
static void plugin_exit(void);
109
static NPError plugin_restart_if_needed(void);
112
* Notes concerning NSPluginWrapper recovery model.
114
* NSPluginWrapper will restart the Viewer if it detected to be
115
* dead. It will not attempt to "replay" the plugin. This means that
116
* if a plugin crashed, its window will remain grayed: only new
117
* instances will start a new viewer.
119
* Each PlugInstance holds a reference to the RPC connection it was
120
* created with. g_rpc_connection can be seen as the "master"
121
* connection (used to initialize and shutdown things). The RPC
122
* connections are reference counted so that when the master
123
* connection is set to a new one, previous connections are still
124
* live. That way, old NPP instances are not passed down with the new
125
* connection and thus can fail early/gracefully in subsequent calls
126
* to NPP_*() functions.
128
* TODO: make NPRuntime aware of per-plugin connections? This
129
* shouldn't matter from the Wrapper side because npruntime requests
130
* come from the Viewer side (see NPN_*() handlers). XXX: even with a
131
* running script (NPClass handlers)?
134
// Minimal time between two plugin restarts in sec
135
#define MIN_RESTART_INTERVAL 1
137
// Consume as many bytes as possible when we are not NPP_WriteReady()
138
// XXX: move to a common place to Wrapper and Viewer
139
#define NPERR_STREAM_BUFSIZ 65536
110
146
#define max(x, y) ((x) > (y) ? (x) : (y))
149
#define PLUGIN_INSTANCE(INSTANCE) plugin_instance(INSTANCE)
151
static inline PluginInstance *plugin_instance(NPP instance)
153
PluginInstance *plugin = (PluginInstance *)instance->pdata;
154
assert(plugin->instance == instance);
158
// Flush the X output buffer
159
static void toolkit_flush(void)
161
// Always prefer gdk_flush() if the master binary is linked against Gtk
162
static void (*INVALID)(void) = (void (*)(void))(intptr_t)-1;
163
static void (*lib_gdk_flush)(void) = NULL;
164
if (lib_gdk_flush == NULL) {
165
if ((lib_gdk_flush = dlsym(RTLD_DEFAULT, "gdk_flush")) == NULL)
166
lib_gdk_flush = INVALID;
168
if (lib_gdk_flush != INVALID) {
174
Display *x_display = NULL;
175
int error = mozilla_funcs.getvalue(NULL, NPNVxDisplay, (void *)&x_display);
176
if (error == NPERR_NO_ERROR && x_display) {
177
XSync(x_display, False);
114
183
/* ====================================================================== */
115
184
/* === RPC communication === */
236
305
NPError ret = NPERR_GENERIC_ERROR;
237
306
switch (rpc_type_of_NPNVariable(variable)) {
307
case RPC_TYPE_UINT32:
310
ret = g_NPN_GetValue(instance, variable, (void *)&n);
311
return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_UINT32, n, RPC_TYPE_INVALID);
238
313
case RPC_TYPE_BOOLEAN:
240
315
PRBool b = PR_FALSE;
332
g_NPN_SetValue(NPP instance, NPNVariable variable, void *value)
334
if (mozilla_funcs.setvalue == NULL)
335
return NPERR_INVALID_FUNCTABLE_ERROR;
337
D(bug("NPN_SetValue instance=%p, variable=%d\n", instance, variable));
338
NPError ret = mozilla_funcs.setvalue(instance, variable, value);
339
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
343
static int handle_NPN_SetValue(rpc_connection_t *connection)
345
D(bug("handle_NPN_SetValue\n"));
348
uint32_t variable, value;
349
int error = rpc_method_get_args(connection,
350
RPC_TYPE_NPP, &instance,
351
RPC_TYPE_UINT32, &variable,
352
RPC_TYPE_BOOLEAN, &value,
355
if (error != RPC_ERROR_NO_ERROR) {
356
npw_perror("NPN_SetValue() get args", error);
360
NPError ret = g_NPN_SetValue(instance, variable, (void *)(uintptr_t)value);
361
return rpc_method_send_reply(connection, RPC_TYPE_INT32, ret, RPC_TYPE_INVALID);
364
// NPN_InvalidateRect
365
static void g_NPN_InvalidateRect(NPP instance, NPRect *invalidRect)
367
if (mozilla_funcs.invalidaterect == NULL)
370
D(bug("NPN_InvalidateRect instance=%p\n", instance));
371
CallNPN_InvalidateRectProc(mozilla_funcs.invalidaterect, instance, invalidRect);
375
static int handle_NPN_InvalidateRect(rpc_connection_t *connection)
377
D(bug("handle_NPN_InvalidateRect\n"));
381
int error = rpc_method_get_args(connection,
382
RPC_TYPE_NPP, &instance,
383
RPC_TYPE_NP_RECT, &invalidRect,
386
if (error != RPC_ERROR_NO_ERROR) {
387
npw_perror("NPN_InvalidateRect() get args", error);
391
g_NPN_InvalidateRect(instance, &invalidRect);
393
return RPC_ERROR_NO_ERROR;
256
397
static NPError g_NPN_GetURL(NPP instance, const char *url, const char *target)
1178
1319
// Creates a new instance of a plug-in
1180
invoke_NPP_New(NPMIMEType mime_type, NPP instance,
1321
invoke_NPP_New(PluginInstance *plugin, NPMIMEType mime_type,
1181
1322
uint16_t mode, int16_t argc, char *argn[], char *argv[],
1182
1323
NPSavedData *saved)
1184
int error = rpc_method_invoke(g_rpc_connection,
1325
int error = rpc_method_invoke(plugin->connection,
1185
1326
RPC_METHOD_NPP_NEW,
1186
RPC_TYPE_UINT32, ((PluginInstance *)instance->pdata)->instance_id,
1327
RPC_TYPE_UINT32, plugin->instance_id,
1187
1328
RPC_TYPE_STRING, mime_type,
1188
1329
RPC_TYPE_INT32, (int32_t)mode,
1189
1330
RPC_TYPE_ARRAY, RPC_TYPE_STRING, (uint32_t)argc, argn,
1217
1358
if (instance == NULL)
1218
1359
return NPERR_INVALID_INSTANCE_ERROR;
1361
// Check if we need to restart the plug-in
1362
NPError ret = plugin_restart_if_needed();
1363
if (ret != NPERR_NO_ERROR)
1220
1366
PluginInstance *plugin = malloc(sizeof(*plugin));
1221
1367
if (plugin == NULL)
1222
1368
return NPERR_OUT_OF_MEMORY_ERROR;
1223
1369
memset(plugin, 0, sizeof(*plugin));
1224
1370
plugin->instance = instance;
1225
1371
plugin->instance_id = id_create(plugin);
1372
plugin->connection = g_rpc_connection;
1226
1373
instance->pdata = plugin;
1375
rpc_connection_ref(plugin->connection);
1228
1377
D(bug("NPP_New instance=%p\n", instance));
1229
NPError ret = invoke_NPP_New(mime_type, instance, mode, argc, argn, argv, saved);
1378
ret = invoke_NPP_New(plugin, mime_type, mode, argc, argn, argv, saved);
1230
1379
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
1241
1390
// Deletes a specific instance of a plug-in
1243
invoke_NPP_Destroy(NPP instance, NPSavedData **save)
1392
invoke_NPP_Destroy(PluginInstance *plugin, NPSavedData **save)
1245
int error = rpc_method_invoke(g_rpc_connection,
1394
int error = rpc_method_invoke(plugin->connection,
1246
1395
RPC_METHOD_NPP_DESTROY,
1247
RPC_TYPE_NPP, instance,
1396
RPC_TYPE_NPP, plugin->instance,
1248
1397
RPC_TYPE_INVALID);
1250
1399
if (error != RPC_ERROR_NO_ERROR) {
1256
1405
NPSavedData *save_area = NULL;
1257
error = rpc_method_wait_for_reply(g_rpc_connection,
1406
error = rpc_method_wait_for_reply(plugin->connection,
1258
1407
RPC_TYPE_INT32, &ret,
1259
1408
RPC_TYPE_NP_SAVED_DATA, &save_area,
1260
1409
RPC_TYPE_INVALID);
1281
1430
if (instance == NULL)
1282
1431
return NPERR_INVALID_INSTANCE_ERROR;
1432
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
1434
return NPERR_INVALID_INSTANCE_ERROR;
1284
1436
D(bug("NPP_Destroy instance=%p\n", instance));
1285
NPError ret = invoke_NPP_Destroy(instance, save);
1437
NPError ret = invoke_NPP_Destroy(plugin, save);
1286
1438
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
1288
PluginInstance *plugin = instance->pdata;
1290
id_remove(plugin->instance_id);
1292
instance->pdata = NULL;
1440
rpc_connection_unref(plugin->connection);
1442
id_remove(plugin->instance_id);
1444
instance->pdata = NULL;
1298
1448
// Tells the plug-in when a window is created, moved, sized, or destroyed
1300
invoke_NPP_SetWindow(NPP instance, NPWindow *window)
1450
invoke_NPP_SetWindow(PluginInstance *plugin, NPWindow *window)
1302
int error = rpc_method_invoke(g_rpc_connection,
1452
int error = rpc_method_invoke(plugin->connection,
1303
1453
RPC_METHOD_NPP_SET_WINDOW,
1304
RPC_TYPE_NPP, instance,
1454
RPC_TYPE_NPP, plugin->instance,
1305
1455
RPC_TYPE_NP_WINDOW, window,
1306
1456
RPC_TYPE_INVALID);
1329
1479
if (instance == NULL)
1330
1480
return NPERR_INVALID_INSTANCE_ERROR;
1481
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
1483
return NPERR_INVALID_INSTANCE_ERROR;
1332
1485
D(bug("NPP_SetWindow instance=%p\n", instance));
1333
NPError ret = invoke_NPP_SetWindow(instance, window);
1486
NPError ret = invoke_NPP_SetWindow(plugin, window);
1334
1487
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
1338
1491
// Allows the browser to query the plug-in for information
1340
invoke_NPP_GetValue(NPP instance, NPPVariable variable, void *value)
1493
invoke_NPP_GetValue(PluginInstance *plugin, NPPVariable variable, void *value)
1342
int error = rpc_method_invoke(g_rpc_connection,
1495
int error = rpc_method_invoke(plugin->connection,
1343
1496
RPC_METHOD_NPP_GET_VALUE,
1344
RPC_TYPE_NPP, instance,
1497
RPC_TYPE_NPP, plugin->instance,
1345
1498
RPC_TYPE_INT32, variable,
1346
1499
RPC_TYPE_INVALID);
1355
1508
case RPC_TYPE_STRING:
1357
1510
char *str = NULL;
1358
error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID);
1511
error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INT32, &ret, RPC_TYPE_STRING, &str, RPC_TYPE_INVALID);
1359
1512
if (error != RPC_ERROR_NO_ERROR) {
1360
1513
npw_perror("NPP_GetValue() wait for reply", error);
1361
1514
ret = NPERR_GENERIC_ERROR;
1384
1537
case RPC_TYPE_INT32:
1387
error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INT32, &n, RPC_TYPE_INVALID);
1540
error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INT32, &n, RPC_TYPE_INVALID);
1388
1541
if (error != RPC_ERROR_NO_ERROR) {
1389
1542
npw_perror("NPP_GetValue() wait for reply", error);
1390
1543
ret = NPERR_GENERIC_ERROR;
1396
1549
case RPC_TYPE_BOOLEAN:
1398
1551
uint32_t b = 0;
1399
error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_BOOLEAN, &b, RPC_TYPE_INVALID);
1552
error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INT32, &ret, RPC_TYPE_BOOLEAN, &b, RPC_TYPE_INVALID);
1400
1553
if (error != RPC_ERROR_NO_ERROR) {
1401
1554
npw_perror("NPP_GetValue() wait for reply", error);
1402
1555
ret = NPERR_GENERIC_ERROR;
1408
1561
case RPC_TYPE_NP_OBJECT:
1410
1563
NPObject *npobj = NULL;
1411
error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_NP_OBJECT, &npobj, RPC_TYPE_INVALID);
1564
error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INT32, &ret, RPC_TYPE_NP_OBJECT, &npobj, RPC_TYPE_INVALID);
1412
1565
if (error != RPC_ERROR_NO_ERROR) {
1413
1566
npw_perror("NPP_GetValue() wait for reply", error);
1414
1567
ret = NPERR_GENERIC_ERROR;
1442
1598
D(bug("NPP_GetValue instance=%p, variable=%d\n", instance, variable));
1443
NPError ret = invoke_NPP_GetValue(instance, variable, value);
1599
NPError ret = invoke_NPP_GetValue(plugin, variable, value);
1444
1600
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
1448
1604
// Sets information about the plug-in
1450
invoke_NPP_SetValue(NPP instance, NPPVariable variable, void *value)
1606
invoke_NPP_SetValue(PluginInstance *plugin, NPPVariable variable, void *value)
1452
1608
UNIMPLEMENTED();
1460
1616
if (instance == NULL)
1461
1617
return NPERR_INVALID_INSTANCE_ERROR;
1618
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
1620
return NPERR_INVALID_INSTANCE_ERROR;
1463
1622
D(bug("NPP_SetValue instance=%p, variable=%d\n", instance, variable));
1464
NPError ret = invoke_NPP_SetValue(instance, variable, value);
1623
NPError ret = invoke_NPP_SetValue(plugin, variable, value);
1465
1624
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
1466
1625
return NPERR_GENERIC_ERROR;
1469
1628
// Notifies the instance of the completion of a URL request
1471
invoke_NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData)
1630
invoke_NPP_URLNotify(PluginInstance *plugin, const char *url, NPReason reason, void *notifyData)
1473
int error = rpc_method_invoke(g_rpc_connection,
1632
int error = rpc_method_invoke(plugin->connection,
1474
1633
RPC_METHOD_NPP_URL_NOTIFY,
1475
RPC_TYPE_NPP, instance,
1634
RPC_TYPE_NPP, plugin->instance,
1476
1635
RPC_TYPE_STRING, url,
1477
1636
RPC_TYPE_INT32, reason,
1478
1637
RPC_TYPE_NP_NOTIFY_DATA, notifyData,
1486
error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INVALID);
1645
error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INVALID);
1488
1647
if (error != RPC_ERROR_NO_ERROR)
1489
1648
npw_perror("NPP_URLNotify() wait for reply", error);
1495
1654
if (instance == NULL)
1656
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
1498
1660
D(bug("NPP_URLNotify instance=%p, url='%s', reason=%d, notifyData=%p\n", instance, url, reason, notifyData));
1499
invoke_NPP_URLNotify(instance, url, reason, notifyData);
1661
invoke_NPP_URLNotify(plugin, url, reason, notifyData);
1500
1662
D(bug(" done\n"));
1503
1665
// Notifies a plug-in instance of a new data stream
1505
invoke_NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype)
1667
invoke_NPP_NewStream(PluginInstance *plugin, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype)
1507
int error = rpc_method_invoke(g_rpc_connection,
1669
int error = rpc_method_invoke(plugin->connection,
1508
1670
RPC_METHOD_NPP_NEW_STREAM,
1509
RPC_TYPE_NPP, instance,
1671
RPC_TYPE_NPP, plugin->instance,
1510
1672
RPC_TYPE_STRING, type,
1511
1673
RPC_TYPE_UINT32, ((StreamInstance *)stream->pdata)->stream_id,
1512
1674
RPC_TYPE_STRING, stream->url,
1526
1688
uint32_t r_stype;
1527
error = rpc_method_wait_for_reply(g_rpc_connection,
1689
error = rpc_method_wait_for_reply(plugin->connection,
1528
1690
RPC_TYPE_INT32, &ret,
1529
1691
RPC_TYPE_UINT32, &r_stype,
1530
1692
RPC_TYPE_NP_NOTIFY_DATA, &stream->notifyData,
1555
1720
stream->pdata = stream_pdata;
1557
1722
D(bug("NPP_NewStream instance=%p\n", instance));
1558
NPError ret = invoke_NPP_NewStream(instance, type, stream, seekable, stype);
1723
NPError ret = invoke_NPP_NewStream(plugin, type, stream, seekable, stype);
1559
1724
D(bug(" return: %d [%s], stype=%s\n", ret, string_of_NPError(ret), string_of_NPStreamType(*stype)));
1563
1728
// Tells the plug-in that a stream is about to be closed or destroyed
1565
invoke_NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
1730
invoke_NPP_DestroyStream(PluginInstance *plugin, NPStream *stream, NPReason reason)
1567
int error = rpc_method_invoke(g_rpc_connection,
1732
int error = rpc_method_invoke(plugin->connection,
1568
1733
RPC_METHOD_NPP_DESTROY_STREAM,
1569
RPC_TYPE_NPP, instance,
1734
RPC_TYPE_NPP, plugin->instance,
1570
1735
RPC_TYPE_NP_STREAM, stream,
1571
1736
RPC_TYPE_INT32, reason,
1572
1737
RPC_TYPE_INVALID);
1595
1760
if (instance == NULL)
1596
1761
return NPERR_INVALID_INSTANCE_ERROR;
1762
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
1764
return NPERR_INVALID_INSTANCE_ERROR;
1598
1766
D(bug("NPP_DestroyStream instance=%p\n", instance));
1599
NPError ret = invoke_NPP_DestroyStream(instance, stream, reason);
1767
NPError ret = invoke_NPP_DestroyStream(plugin, stream, reason);
1600
1768
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
1602
1770
StreamInstance *stream_pdata = stream->pdata;
1612
1780
// Provides a local file name for the data from a stream
1614
invoke_NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname)
1782
invoke_NPP_StreamAsFile(PluginInstance *plugin, NPStream *stream, const char *fname)
1616
int error = rpc_method_invoke(g_rpc_connection,
1784
int error = rpc_method_invoke(plugin->connection,
1617
1785
RPC_METHOD_NPP_STREAM_AS_FILE,
1618
RPC_TYPE_NPP, instance,
1786
RPC_TYPE_NPP, plugin->instance,
1619
1787
RPC_TYPE_NP_STREAM, stream,
1620
1788
RPC_TYPE_STRING, fname,
1621
1789
RPC_TYPE_INVALID);
1628
error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INVALID);
1796
error = rpc_method_wait_for_reply(plugin->connection, RPC_TYPE_INVALID);
1630
1798
if (error != RPC_ERROR_NO_ERROR)
1631
1799
npw_perror("NPP_StreamAsFile() wait for reply", error);
1637
1805
if (instance == NULL)
1807
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
1640
1811
D(bug("NPP_StreamAsFile instance=%p\n", instance));
1641
invoke_NPP_StreamAsFile(instance, stream, fname);
1812
invoke_NPP_StreamAsFile(plugin, stream, fname);
1642
1813
D(bug(" done\n"));
1645
1816
// Determines maximum number of bytes that the plug-in can consume
1647
invoke_NPP_WriteReady(NPP instance, NPStream *stream)
1818
invoke_NPP_WriteReady(PluginInstance *plugin, NPStream *stream)
1649
int error = rpc_method_invoke(g_rpc_connection,
1820
int error = rpc_method_invoke(plugin->connection,
1650
1821
RPC_METHOD_NPP_WRITE_READY,
1651
RPC_TYPE_NPP, instance,
1822
RPC_TYPE_NPP, plugin->instance,
1652
1823
RPC_TYPE_NP_STREAM, stream,
1653
1824
RPC_TYPE_INVALID);
1655
1826
if (error != RPC_ERROR_NO_ERROR) {
1656
1827
npw_perror("NPP_WriteReady() invoke", error);
1828
return NPERR_STREAM_BUFSIZ;
1661
error = rpc_method_wait_for_reply(g_rpc_connection,
1832
error = rpc_method_wait_for_reply(plugin->connection,
1662
1833
RPC_TYPE_INT32, &ret,
1663
1834
RPC_TYPE_INVALID);
1665
1836
if (error != RPC_ERROR_NO_ERROR) {
1666
1837
npw_perror("NPP_WriteReady() wait for reply", error);
1838
return NPERR_STREAM_BUFSIZ;
1674
1845
g_NPP_WriteReady(NPP instance, NPStream *stream)
1676
1847
if (instance == NULL)
1849
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
1679
1853
D(bug("NPP_WriteReady instance=%p\n", instance));
1680
int32 ret = invoke_NPP_WriteReady(instance, stream);
1854
int32 ret = invoke_NPP_WriteReady(plugin, stream);
1681
1855
D(bug(" return: %d\n", ret));
1686
1860
// Delivers data to a plug-in instance
1688
invoke_NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buf)
1862
invoke_NPP_Write(PluginInstance *plugin, NPStream *stream, int32 offset, int32 len, void *buf)
1690
int error = rpc_method_invoke(g_rpc_connection,
1864
int error = rpc_method_invoke(plugin->connection,
1691
1865
RPC_METHOD_NPP_WRITE,
1692
RPC_TYPE_NPP, instance,
1866
RPC_TYPE_NPP, plugin->instance,
1693
1867
RPC_TYPE_NP_STREAM, stream,
1694
1868
RPC_TYPE_INT32, offset,
1695
1869
RPC_TYPE_ARRAY, RPC_TYPE_CHAR, len, buf,
1719
1893
if (instance == NULL)
1895
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
1722
1899
D(bug("NPP_Write instance=%p\n", instance));
1723
int32 ret = invoke_NPP_Write(instance, stream, offset, len, buf);
1900
int32 ret = invoke_NPP_Write(plugin, stream, offset, len, buf);
1724
1901
D(bug(" return: %d\n", ret));
1729
1906
// Requests a platform-specific print operation for an embedded or full-screen plug-in
1730
static void invoke_NPP_Print(NPP instance, NPPrint *PrintInfo)
1907
static void invoke_NPP_Print(PluginInstance *plugin, NPPrint *PrintInfo)
1732
1909
NPPrintCallbackStruct *platformPrint;
1733
1910
switch (PrintInfo->mode) {
1746
1923
platform_print_id = id_create(platformPrint);
1747
1924
D(bug(" platformPrint=%p\n", platformPrint));
1749
int error = rpc_method_invoke(g_rpc_connection,
1926
int error = rpc_method_invoke(plugin->connection,
1750
1927
RPC_METHOD_NPP_PRINT,
1751
RPC_TYPE_NPP, instance,
1928
RPC_TYPE_NPP, plugin->instance,
1752
1929
RPC_TYPE_UINT32, platform_print_id,
1753
1930
RPC_TYPE_NP_PRINT, PrintInfo,
1754
1931
RPC_TYPE_INVALID);
1781
1958
if (instance == NULL)
1960
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
1784
1964
if (PrintInfo == NULL)
1787
1967
D(bug("NPP_Print instance=%p\n", instance));
1788
invoke_NPP_Print(instance, PrintInfo);
1968
invoke_NPP_Print(plugin, PrintInfo);
1789
1969
D(bug(" done\n"));
1792
1972
// Delivers a platform-specific window event to the instance
1793
static int16 invoke_NPP_HandleEvent(NPP instance, void *event)
1973
static int16 invoke_NPP_HandleEvent(PluginInstance *plugin, void *event)
1975
int error = rpc_method_invoke(plugin->connection,
1976
RPC_METHOD_NPP_HANDLE_EVENT,
1977
RPC_TYPE_NPP, plugin->instance,
1978
RPC_TYPE_NP_EVENT, event,
1981
if (error != RPC_ERROR_NO_ERROR) {
1982
npw_perror("NPP_HandleEvent() invoke", error);
1983
return NPERR_GENERIC_ERROR;
1987
error = rpc_method_wait_for_reply(plugin->connection,
1988
RPC_TYPE_INT32, &ret,
1991
if (error != RPC_ERROR_NO_ERROR) {
1992
npw_perror("NPP_HandleEvent() wait for reply", error);
1993
return NPERR_GENERIC_ERROR;
1800
1999
static int16 g_NPP_HandleEvent(NPP instance, void *event)
1802
2001
if (instance == NULL)
1803
2002
return NPERR_INVALID_INSTANCE_ERROR;
2004
PluginInstance *plugin = PLUGIN_INSTANCE(instance);
2006
return NPERR_INVALID_INSTANCE_ERROR;
2008
if (((NPEvent *)event)->type == GraphicsExpose) {
2009
/* XXX: flush the X output buffer so that the call to
2010
gdk_pixmap_foreign_new() in the viewer can work */
1805
2014
D(bug("NPP_HandleEvent instance=%p\n", instance));
1806
int16 ret = invoke_NPP_HandleEvent(instance, event);
2015
int16 ret = invoke_NPP_HandleEvent(plugin, event);
1807
2016
D(bug(" return: ret\n", ret));
2312
2521
// Provides global initialization for a plug-in
2523
invoke_NP_Initialize(uint32_t npapi_version)
2525
int error = rpc_method_invoke(g_rpc_connection,
2526
RPC_METHOD_NP_INITIALIZE,
2527
RPC_TYPE_UINT32, npapi_version,
2530
if (error != RPC_ERROR_NO_ERROR) {
2531
npw_perror("NP_Initialize() invoke", error);
2532
return NPERR_MODULE_LOAD_FAILED_ERROR;
2536
error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INVALID);
2538
if (error != RPC_ERROR_NO_ERROR) {
2539
npw_perror("NP_Initialize() wait for reply", error);
2540
return NPERR_MODULE_LOAD_FAILED_ERROR;
2314
2547
NP_Initialize(NPNetscapeFuncs *moz_funcs, NPPluginFuncs *plugin_funcs)
2375
2608
// pass down common NPAPI version supported by both the underlying
2376
2609
// browser and the thunking capabilities of nspluginwrapper
2377
uint32_t version = min(moz_funcs->version, plugin_funcs->version);
2379
int error = rpc_method_invoke(g_rpc_connection,
2380
RPC_METHOD_NP_INITIALIZE,
2381
RPC_TYPE_UINT32, (uint32_t)version,
2384
if (error != RPC_ERROR_NO_ERROR) {
2385
npw_perror("NP_Initialize() invoke", error);
2386
return NPERR_MODULE_LOAD_FAILED_ERROR;
2390
error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INVALID);
2392
if (error != RPC_ERROR_NO_ERROR) {
2393
npw_perror("NP_Initialize() wait for reply", error);
2394
return NPERR_MODULE_LOAD_FAILED_ERROR;
2610
npapi_version = min(moz_funcs->version, plugin_funcs->version);
2612
NPError ret = invoke_NP_Initialize(npapi_version);
2397
2613
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
2492
2717
if (sscanf(line, "%s %d", tag, &len) == 2) {
2493
2718
char *str = malloc(++len);
2494
2719
if (str && fgets(str, len, viewer_fp)) {
2495
2721
if (strcmp(tag, "PLUGIN_NAME") == 0)
2496
g_plugin.name = str;
2722
ptag = &g_plugin.name;
2497
2723
else if (strcmp(tag, "PLUGIN_DESC") == 0)
2498
g_plugin.description = str;
2724
ptag = &g_plugin.description;
2499
2725
else if (strcmp(tag, "PLUGIN_MIME") == 0)
2500
g_plugin.formats = str;
2726
ptag = &g_plugin.formats;
2528
2756
// Initialize browser-side RPC communication channel
2529
if (rpc_add_np_marshalers() < 0) {
2530
npw_printf("ERROR: failed to initialize browser-side marshalers\n");
2533
2757
if ((g_rpc_connection = rpc_init_client(connection_path)) == NULL) {
2534
2758
npw_printf("ERROR: failed to initialize plugin-side RPC client connection\n");
2761
if (rpc_add_np_marshalers(g_rpc_connection) < 0) {
2762
npw_printf("ERROR: failed to initialize browser-side marshalers\n");
2537
2765
static const rpc_method_descriptor_t vtable[] = {
2538
2766
{ RPC_METHOD_NPN_USER_AGENT, handle_NPN_UserAgent },
2539
2767
{ RPC_METHOD_NPN_GET_VALUE, handle_NPN_GetValue },
2768
{ RPC_METHOD_NPN_SET_VALUE, handle_NPN_SetValue },
2540
2769
{ RPC_METHOD_NPN_GET_URL, handle_NPN_GetURL },
2541
2770
{ RPC_METHOD_NPN_GET_URL_NOTIFY, handle_NPN_GetURLNotify },
2542
2771
{ RPC_METHOD_NPN_POST_URL, handle_NPN_PostURL },
2549
2778
{ RPC_METHOD_NPN_WRITE, handle_NPN_Write },
2550
2779
{ RPC_METHOD_NPN_PUSH_POPUPS_ENABLED_STATE, handle_NPN_PushPopupsEnabledState },
2551
2780
{ RPC_METHOD_NPN_POP_POPUPS_ENABLED_STATE, handle_NPN_PopPopupsEnabledState },
2781
{ RPC_METHOD_NPN_INVALIDATE_RECT, handle_NPN_InvalidateRect },
2552
2782
{ RPC_METHOD_NPN_CREATE_OBJECT, handle_NPN_CreateObject },
2553
2783
{ RPC_METHOD_NPN_RETAIN_OBJECT, handle_NPN_RetainObject },
2554
2784
{ RPC_METHOD_NPN_RELEASE_OBJECT, handle_NPN_ReleaseObject },
2576
2806
{ RPC_METHOD_NPCLASS_SET_PROPERTY, npclass_handle_SetProperty },
2577
2807
{ RPC_METHOD_NPCLASS_REMOVE_PROPERTY, npclass_handle_RemoveProperty },
2579
if (rpc_method_add_callbacks(g_rpc_connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
2809
if (rpc_connection_add_method_descriptors(g_rpc_connection, vtable, sizeof(vtable) / sizeof(vtable[0])) < 0) {
2580
2810
npw_printf("ERROR: failed to setup NPN method callbacks\n");
2708
2938
g_plugin.description = NULL;
2942
static NPError plugin_restart(void)
2944
if (g_plugin.is_wrapper)
2945
return NPERR_NO_ERROR;
2949
g_plugin.initialized = 0;
2950
g_plugin.viewer_pid = -1;
2951
g_plugin.is_wrapper = 0;
2953
// And start it again
2955
if (g_plugin.initialized <= 0)
2956
return NPERR_MODULE_LOAD_FAILED_ERROR;
2958
return invoke_NP_Initialize(npapi_version);
2961
static NPError plugin_restart_if_needed(void)
2963
if (rpc_status(g_rpc_connection) != RPC_STATUS_ACTIVE) {
2964
static time_t last_restart = 0;
2965
time_t now = time(NULL);
2966
if (now - last_restart < MIN_RESTART_INTERVAL)
2967
return NPERR_GENERIC_ERROR;
2970
D(bug("Restart plugins viewer\n"));
2971
NPError ret = plugin_restart();
2972
D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
2976
return NPERR_NO_ERROR;