~ubuntu-branches/ubuntu/lucid/nspluginwrapper/lucid

« back to all changes in this revision

Viewing changes to src/npw-wrapper.c

  • Committer: Bazaar Package Importer
  • Author(s): Sasa Bodiroza
  • Date: 2008-08-28 00:48:30 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20080828004830-f3m3fjnqlqt2r6dh
Tags: 1.1.0-0ubuntu1
Add libcurl4-gnutls-dev as build-depenedency

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  npw-wrapper.c - Host Mozilla plugin (loads the actual viewer)
3
3
 *
4
 
 *  nspluginwrapper (C) 2005-2007 Gwenole Beauchesne
 
4
 *  nspluginwrapper (C) 2005-2008 Gwenole Beauchesne
5
5
 *
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.
15
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., 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.
19
19
 */
20
20
 
21
21
#define _GNU_SOURCE 1 /* RTLD_DEFAULT */
22
22
#include "sysdeps.h"
23
23
 
 
24
#include <assert.h>
24
25
#include <stdio.h>
25
26
#include <stdlib.h>
26
27
#include <string.h>
73
74
// Netscape exported functions
74
75
static NPNetscapeFuncs mozilla_funcs;
75
76
 
 
77
// NPAPI version nspluginwrapper supports
 
78
static int npapi_version = 0;
 
79
 
76
80
// Wrapper plugin data
77
81
typedef struct {
78
82
  int initialized;
89
93
typedef struct _PluginInstance {
90
94
  NPP instance;
91
95
  uint32_t instance_id;
 
96
  rpc_connection_t *connection;
92
97
} PluginInstance;
93
98
 
94
99
// Plugin side data for an NPStream instance
101
106
// Prototypes
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);
 
110
 
 
111
/*
 
112
 *  Notes concerning NSPluginWrapper recovery model.
 
113
 *
 
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.
 
118
 *
 
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.
 
127
 *
 
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)?
 
132
 */
 
133
 
 
134
// Minimal time between two plugin restarts in sec
 
135
#define MIN_RESTART_INTERVAL 1
 
136
 
 
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
104
140
 
105
141
// Helpers
106
142
#ifndef min
110
146
#define max(x, y) ((x) > (y) ? (x) : (y))
111
147
#endif
112
148
 
 
149
#define PLUGIN_INSTANCE(INSTANCE) plugin_instance(INSTANCE)
 
150
 
 
151
static inline PluginInstance *plugin_instance(NPP instance)
 
152
{
 
153
  PluginInstance *plugin = (PluginInstance *)instance->pdata;
 
154
  assert(plugin->instance == instance);
 
155
  return plugin;
 
156
}
 
157
 
 
158
// Flush the X output buffer
 
159
static void toolkit_flush(void)
 
160
{
 
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;
 
167
  }
 
168
  if (lib_gdk_flush != INVALID) {
 
169
        lib_gdk_flush();
 
170
        return;
 
171
  }
 
172
 
 
173
  // Try raw X11
 
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);
 
178
        return;
 
179
  }
 
180
}
 
181
 
113
182
 
114
183
/* ====================================================================== */
115
184
/* === RPC communication                                              === */
235
304
 
236
305
  NPError ret = NPERR_GENERIC_ERROR;
237
306
  switch (rpc_type_of_NPNVariable(variable)) {
 
307
  case RPC_TYPE_UINT32:
 
308
        {
 
309
          uint32_t n = 0;
 
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);
 
312
        }
238
313
  case RPC_TYPE_BOOLEAN:
239
314
        {
240
315
          PRBool b = PR_FALSE;
252
327
  abort();
253
328
}
254
329
 
 
330
// NPN_SetValue
 
331
static NPError
 
332
g_NPN_SetValue(NPP instance, NPNVariable variable, void *value)
 
333
{
 
334
  if (mozilla_funcs.setvalue == NULL)
 
335
        return NPERR_INVALID_FUNCTABLE_ERROR;
 
336
 
 
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)));
 
340
  return ret;
 
341
}
 
342
 
 
343
static int handle_NPN_SetValue(rpc_connection_t *connection)
 
344
{
 
345
  D(bug("handle_NPN_SetValue\n"));
 
346
 
 
347
  NPP instance;
 
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,
 
353
                                                                  RPC_TYPE_INVALID);
 
354
 
 
355
  if (error != RPC_ERROR_NO_ERROR) {
 
356
        npw_perror("NPN_SetValue() get args", error);
 
357
        return error;
 
358
  }
 
359
 
 
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);
 
362
}
 
363
 
 
364
// NPN_InvalidateRect
 
365
static void g_NPN_InvalidateRect(NPP instance, NPRect *invalidRect)
 
366
{
 
367
  if (mozilla_funcs.invalidaterect == NULL)
 
368
        return;
 
369
 
 
370
  D(bug("NPN_InvalidateRect instance=%p\n", instance));
 
371
  CallNPN_InvalidateRectProc(mozilla_funcs.invalidaterect, instance, invalidRect);
 
372
  D(bug(" done\n"));
 
373
}
 
374
 
 
375
static int handle_NPN_InvalidateRect(rpc_connection_t *connection)
 
376
{
 
377
  D(bug("handle_NPN_InvalidateRect\n"));
 
378
 
 
379
  NPP instance;
 
380
  NPRect invalidRect;
 
381
  int error = rpc_method_get_args(connection,
 
382
                                                                  RPC_TYPE_NPP, &instance,
 
383
                                                                  RPC_TYPE_NP_RECT, &invalidRect,
 
384
                                                                  RPC_TYPE_INVALID);
 
385
 
 
386
  if (error != RPC_ERROR_NO_ERROR) {
 
387
        npw_perror("NPN_InvalidateRect() get args", error);
 
388
        return error;
 
389
  }
 
390
 
 
391
  g_NPN_InvalidateRect(instance, &invalidRect);
 
392
 
 
393
  return RPC_ERROR_NO_ERROR;
 
394
}
 
395
 
255
396
// NPN_GetURL
256
397
static NPError g_NPN_GetURL(NPP instance, const char *url, const char *target)
257
398
{
1177
1318
 
1178
1319
// Creates a new instance of a plug-in
1179
1320
static NPError
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)
1183
1324
{
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,
1197
1338
  }
1198
1339
 
1199
1340
  int32_t ret;
1200
 
  error = rpc_method_wait_for_reply(g_rpc_connection,
 
1341
  error = rpc_method_wait_for_reply(plugin->connection,
1201
1342
                                                                        RPC_TYPE_INT32, &ret,
1202
1343
                                                                        RPC_TYPE_INVALID);
1203
1344
 
1216
1357
{
1217
1358
  if (instance == NULL)
1218
1359
        return NPERR_INVALID_INSTANCE_ERROR;
1219
 
 
 
1360
        
 
1361
  // Check if we need to restart the plug-in
 
1362
  NPError ret = plugin_restart_if_needed();
 
1363
  if (ret != NPERR_NO_ERROR)
 
1364
        return ret;
 
1365
                
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;
1227
1374
 
 
1375
  rpc_connection_ref(plugin->connection);
 
1376
 
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)));
1231
1380
 
1232
1381
  if (saved) {
1240
1389
 
1241
1390
// Deletes a specific instance of a plug-in
1242
1391
static NPError
1243
 
invoke_NPP_Destroy(NPP instance, NPSavedData **save)
 
1392
invoke_NPP_Destroy(PluginInstance *plugin, NPSavedData **save)
1244
1393
{
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);
1249
1398
 
1250
1399
  if (error != RPC_ERROR_NO_ERROR) {
1254
1403
 
1255
1404
  int32_t ret;
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);
1280
1429
{
1281
1430
  if (instance == NULL)
1282
1431
        return NPERR_INVALID_INSTANCE_ERROR;
 
1432
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1433
  if (plugin == NULL)
 
1434
        return NPERR_INVALID_INSTANCE_ERROR;
1283
1435
 
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)));
1287
1439
 
1288
 
  PluginInstance *plugin = instance->pdata;
1289
 
  if (plugin) {
1290
 
        id_remove(plugin->instance_id);
1291
 
        free(plugin);
1292
 
        instance->pdata = NULL;
1293
 
  }
 
1440
  rpc_connection_unref(plugin->connection);
1294
1441
 
 
1442
  id_remove(plugin->instance_id);
 
1443
  free(plugin);
 
1444
  instance->pdata = NULL;
1295
1445
  return ret;
1296
1446
}
1297
1447
 
1298
1448
// Tells the plug-in when a window is created, moved, sized, or destroyed
1299
1449
static NPError
1300
 
invoke_NPP_SetWindow(NPP instance, NPWindow *window)
 
1450
invoke_NPP_SetWindow(PluginInstance *plugin, NPWindow *window)
1301
1451
{
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);
1307
1457
 
1311
1461
  }
1312
1462
 
1313
1463
  int32_t ret;
1314
 
  error = rpc_method_wait_for_reply(g_rpc_connection,
 
1464
  error = rpc_method_wait_for_reply(plugin->connection,
1315
1465
                                                                        RPC_TYPE_INT32, &ret,
1316
1466
                                                                        RPC_TYPE_INVALID);
1317
1467
 
1328
1478
{
1329
1479
  if (instance == NULL)
1330
1480
        return NPERR_INVALID_INSTANCE_ERROR;
 
1481
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1482
  if (plugin == NULL)
 
1483
        return NPERR_INVALID_INSTANCE_ERROR;
1331
1484
 
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)));
1335
1488
  return ret;
1336
1489
}
1337
1490
 
1338
1491
// Allows the browser to query the plug-in for information
1339
1492
static NPError
1340
 
invoke_NPP_GetValue(NPP instance, NPPVariable variable, void *value)
 
1493
invoke_NPP_GetValue(PluginInstance *plugin, NPPVariable variable, void *value)
1341
1494
{
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);
1347
1500
 
1355
1508
  case RPC_TYPE_STRING:
1356
1509
        {
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:
1385
1538
        {
1386
1539
          int32_t n = 0;
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:
1397
1550
        {
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:
1409
1562
        {
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;
1427
1580
{
1428
1581
  if (instance == NULL)
1429
1582
        return NPERR_INVALID_INSTANCE_ERROR;
 
1583
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1584
  if (plugin == NULL)
 
1585
        return NPERR_INVALID_INSTANCE_ERROR;
1430
1586
 
1431
1587
  switch (rpc_type_of_NPPVariable(variable)) {
1432
1588
  case RPC_TYPE_STRING:
1440
1596
  }
1441
1597
 
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)));
1445
1601
  return ret;
1446
1602
}
1447
1603
 
1448
1604
// Sets information about the plug-in
1449
1605
static NPError
1450
 
invoke_NPP_SetValue(NPP instance, NPPVariable variable, void *value)
 
1606
invoke_NPP_SetValue(PluginInstance *plugin, NPPVariable variable, void *value)
1451
1607
{
1452
1608
  UNIMPLEMENTED();
1453
1609
 
1459
1615
{
1460
1616
  if (instance == NULL)
1461
1617
        return NPERR_INVALID_INSTANCE_ERROR;
 
1618
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1619
  if (plugin == NULL)
 
1620
        return NPERR_INVALID_INSTANCE_ERROR;
1462
1621
 
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;
1467
1626
}
1468
1627
 
1469
1628
// Notifies the instance of the completion of a URL request
1470
1629
static void
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)
1472
1631
{
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,
1483
1642
        return;
1484
1643
  }
1485
1644
 
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);
1487
1646
  
1488
1647
  if (error != RPC_ERROR_NO_ERROR)
1489
1648
        npw_perror("NPP_URLNotify() wait for reply", error);
1494
1653
{
1495
1654
  if (instance == NULL)
1496
1655
        return;
 
1656
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1657
  if (plugin == NULL)
 
1658
        return;
1497
1659
 
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"));
1501
1663
}
1502
1664
 
1503
1665
// Notifies a plug-in instance of a new data stream
1504
1666
static NPError
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)
1506
1668
{
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,
1524
1686
 
1525
1687
  int32_t ret;
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,
1544
1706
{
1545
1707
  if (instance == NULL)
1546
1708
        return NPERR_INVALID_INSTANCE_ERROR;
 
1709
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1710
  if (plugin == NULL)
 
1711
        return NPERR_INVALID_INSTANCE_ERROR;
1547
1712
 
1548
1713
  StreamInstance *stream_pdata = malloc(sizeof(*stream_pdata));
1549
1714
  if (stream_pdata == NULL)
1555
1720
  stream->pdata = stream_pdata;
1556
1721
 
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)));
1560
1725
  return ret;
1561
1726
}
1562
1727
 
1563
1728
// Tells the plug-in that a stream is about to be closed or destroyed
1564
1729
static NPError
1565
 
invoke_NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
 
1730
invoke_NPP_DestroyStream(PluginInstance *plugin, NPStream *stream, NPReason reason)
1566
1731
{
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);
1577
1742
  }
1578
1743
 
1579
1744
  int32_t ret;
1580
 
  error = rpc_method_wait_for_reply(g_rpc_connection,
 
1745
  error = rpc_method_wait_for_reply(plugin->connection,
1581
1746
                                                                        RPC_TYPE_INT32, &ret,
1582
1747
                                                                        RPC_TYPE_INVALID);
1583
1748
 
1594
1759
{
1595
1760
  if (instance == NULL)
1596
1761
        return NPERR_INVALID_INSTANCE_ERROR;
 
1762
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1763
  if (plugin == NULL)
 
1764
        return NPERR_INVALID_INSTANCE_ERROR;
1597
1765
 
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)));
1601
1769
 
1602
1770
  StreamInstance *stream_pdata = stream->pdata;
1611
1779
 
1612
1780
// Provides a local file name for the data from a stream
1613
1781
static void
1614
 
invoke_NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname)
 
1782
invoke_NPP_StreamAsFile(PluginInstance *plugin, NPStream *stream, const char *fname)
1615
1783
{
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);
1625
1793
        return;
1626
1794
  }
1627
1795
 
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);
1629
1797
 
1630
1798
  if (error != RPC_ERROR_NO_ERROR)
1631
1799
        npw_perror("NPP_StreamAsFile() wait for reply", error);
1636
1804
{
1637
1805
  if (instance == NULL)
1638
1806
        return;
 
1807
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1808
  if (plugin == NULL)
 
1809
        return;
1639
1810
 
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"));
1643
1814
}
1644
1815
 
1645
1816
// Determines maximum number of bytes that the plug-in can consume
1646
1817
static int32
1647
 
invoke_NPP_WriteReady(NPP instance, NPStream *stream)
 
1818
invoke_NPP_WriteReady(PluginInstance *plugin, NPStream *stream)
1648
1819
{
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);
1654
1825
 
1655
1826
  if (error != RPC_ERROR_NO_ERROR) {
1656
1827
        npw_perror("NPP_WriteReady() invoke", error);
1657
 
        return 0;
 
1828
        return NPERR_STREAM_BUFSIZ;
1658
1829
  }
1659
1830
 
1660
1831
  int32_t ret;
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);
1664
1835
 
1665
1836
  if (error != RPC_ERROR_NO_ERROR) {
1666
1837
        npw_perror("NPP_WriteReady() wait for reply", error);
1667
 
        return 0;
 
1838
        return NPERR_STREAM_BUFSIZ;
1668
1839
  }
1669
1840
 
1670
1841
  return ret;
1674
1845
g_NPP_WriteReady(NPP instance, NPStream *stream)
1675
1846
{
1676
1847
  if (instance == NULL)
1677
 
        return -1;
 
1848
        return 0;
 
1849
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1850
  if (plugin == NULL)
 
1851
        return 0;
1678
1852
 
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));
1682
1856
  return ret;
1683
1857
}
1685
1859
 
1686
1860
// Delivers data to a plug-in instance
1687
1861
static int32
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)
1689
1863
{
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,
1701
1875
  }
1702
1876
 
1703
1877
  int32_t ret;
1704
 
  error = rpc_method_wait_for_reply(g_rpc_connection,
 
1878
  error = rpc_method_wait_for_reply(plugin->connection,
1705
1879
                                                                        RPC_TYPE_INT32, &ret,
1706
1880
                                                                        RPC_TYPE_INVALID);
1707
1881
 
1718
1892
{
1719
1893
  if (instance == NULL)
1720
1894
        return -1;
 
1895
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1896
  if (plugin == NULL)
 
1897
        return -1;
1721
1898
 
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));
1725
1902
  return ret;
1726
1903
}
1727
1904
 
1728
1905
 
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)
1731
1908
{
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));
1748
1925
 
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);
1759
1936
  }
1760
1937
 
1761
1938
  uint32_t pluginPrinted;
1762
 
  error = rpc_method_wait_for_reply(g_rpc_connection,
 
1939
  error = rpc_method_wait_for_reply(plugin->connection,
1763
1940
                                                                        RPC_TYPE_BOOLEAN, &pluginPrinted,
1764
1941
                                                                        RPC_TYPE_INVALID);
1765
1942
 
1780
1957
{
1781
1958
  if (instance == NULL)
1782
1959
        return;
 
1960
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
1961
  if (plugin == NULL)
 
1962
        return;
1783
1963
 
1784
1964
  if (PrintInfo == NULL)
1785
1965
        return;
1786
1966
 
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"));
1790
1970
}
1791
1971
 
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)
1794
1974
{
1795
 
  UNIMPLEMENTED();
1796
 
 
1797
 
  return 0;
 
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,
 
1979
                                                                RPC_TYPE_INVALID);
 
1980
 
 
1981
  if (error != RPC_ERROR_NO_ERROR) {
 
1982
        npw_perror("NPP_HandleEvent() invoke", error);
 
1983
        return NPERR_GENERIC_ERROR;
 
1984
  }
 
1985
 
 
1986
  int32_t ret;
 
1987
  error = rpc_method_wait_for_reply(plugin->connection,
 
1988
                                                                        RPC_TYPE_INT32, &ret,
 
1989
                                                                        RPC_TYPE_INVALID);
 
1990
 
 
1991
  if (error != RPC_ERROR_NO_ERROR) {
 
1992
        npw_perror("NPP_HandleEvent() wait for reply", error);
 
1993
        return NPERR_GENERIC_ERROR;
 
1994
  }
 
1995
 
 
1996
  return ret;
1798
1997
}
1799
1998
 
1800
1999
static int16 g_NPP_HandleEvent(NPP instance, void *event)
1802
2001
  if (instance == NULL)
1803
2002
        return NPERR_INVALID_INSTANCE_ERROR;
1804
2003
 
 
2004
  PluginInstance *plugin = PLUGIN_INSTANCE(instance);
 
2005
  if (plugin == NULL)
 
2006
        return NPERR_INVALID_INSTANCE_ERROR;
 
2007
 
 
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 */
 
2011
        toolkit_flush();
 
2012
  }
 
2013
 
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));
1808
2017
  return ret;
1809
2018
}
1812
2021
NPError
1813
2022
NP_GetValue(void *future, NPPVariable variable, void *value)
1814
2023
{
1815
 
  D(bug("NP_GetValue\n"));
 
2024
  D(bug("NP_GetValue variable=%d\n", variable));
1816
2025
 
1817
2026
  if (g_plugin.initialized == 0)
1818
2027
        plugin_init(0);
2206
2415
g_LONG64_NPP_WriteReady(NPP instance, void *stream)
2207
2416
{
2208
2417
  if (instance == NULL)
2209
 
        return -1L;
 
2418
        return 0;
2210
2419
 
2211
2420
  if (stream == NULL)
2212
 
        return -1L;
 
2421
        return 0;
2213
2422
 
2214
2423
  return (int64)(int32)g_NPP_WriteReady(instance, NP_STREAM32(stream));
2215
2424
}
2310
2519
}
2311
2520
 
2312
2521
// Provides global initialization for a plug-in
 
2522
static NPError
 
2523
invoke_NP_Initialize(uint32_t npapi_version)
 
2524
{
 
2525
  int error = rpc_method_invoke(g_rpc_connection,
 
2526
                                                                RPC_METHOD_NP_INITIALIZE,
 
2527
                                                                RPC_TYPE_UINT32, npapi_version,
 
2528
                                                                RPC_TYPE_INVALID);
 
2529
 
 
2530
  if (error != RPC_ERROR_NO_ERROR) {
 
2531
        npw_perror("NP_Initialize() invoke", error);
 
2532
        return NPERR_MODULE_LOAD_FAILED_ERROR;
 
2533
  }
 
2534
 
 
2535
  int32_t ret;
 
2536
  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INVALID);
 
2537
 
 
2538
  if (error != RPC_ERROR_NO_ERROR) {
 
2539
        npw_perror("NP_Initialize() wait for reply", error);
 
2540
        return NPERR_MODULE_LOAD_FAILED_ERROR;
 
2541
  }
 
2542
 
 
2543
  return ret;
 
2544
}
 
2545
 
2313
2546
NPError
2314
2547
NP_Initialize(NPNetscapeFuncs *moz_funcs, NPPluginFuncs *plugin_funcs)
2315
2548
{
2374
2607
 
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);
2378
 
 
2379
 
  int error = rpc_method_invoke(g_rpc_connection,
2380
 
                                                                RPC_METHOD_NP_INITIALIZE,
2381
 
                                                                RPC_TYPE_UINT32, (uint32_t)version,
2382
 
                                                                RPC_TYPE_INVALID);
2383
 
 
2384
 
  if (error != RPC_ERROR_NO_ERROR) {
2385
 
        npw_perror("NP_Initialize() invoke", error);
2386
 
        return NPERR_MODULE_LOAD_FAILED_ERROR;
2387
 
  }
2388
 
 
2389
 
  int32_t ret;
2390
 
  error = rpc_method_wait_for_reply(g_rpc_connection, RPC_TYPE_INT32, &ret, RPC_TYPE_INVALID);
2391
 
 
2392
 
  if (error != RPC_ERROR_NO_ERROR) {
2393
 
        npw_perror("NP_Initialize() wait for reply", error);
2394
 
        return NPERR_MODULE_LOAD_FAILED_ERROR;
2395
 
  }
2396
 
 
 
2610
  npapi_version = min(moz_funcs->version, plugin_funcs->version);
 
2611
 
 
2612
  NPError ret = invoke_NP_Initialize(npapi_version);
2397
2613
  D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
2398
2614
  return ret;
2399
2615
}
2485
2701
          int len = strlen(line);
2486
2702
          if (len == 0)
2487
2703
                continue;
 
2704
          if (line[len - 1] != '\n') {
 
2705
                // Consume the whole line, we can't see our tags here
 
2706
                while (fgets(line, sizeof(line), viewer_fp)) {
 
2707
                  len = strlen(line);
 
2708
                  if (line > 0 && line[len - 1] == '\n')
 
2709
                        break;
 
2710
                }
 
2711
                continue;
 
2712
          }
2488
2713
          line[len - 1] = '\0';
2489
2714
 
2490
2715
          // Parse line
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)) {
 
2720
                  char **ptag = NULL;
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;
 
2727
                  if (ptag)
 
2728
                        *ptag = str;
2501
2729
                }
2502
2730
          }
2503
2731
        }
2526
2754
  }
2527
2755
 
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");
2531
 
        return;
2532
 
  }
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");
2535
2759
        return;
2536
2760
  }
 
2761
  if (rpc_add_np_marshalers(g_rpc_connection) < 0) {
 
2762
        npw_printf("ERROR: failed to initialize browser-side marshalers\n");
 
2763
        return;
 
2764
  }
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 },
2578
2808
  };
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");
2581
2811
        return;
2582
2812
  }
2657
2887
  }
2658
2888
 
2659
2889
  if (g_rpc_connection) {
2660
 
        rpc_exit(g_rpc_connection);
 
2890
        rpc_connection_unref(g_rpc_connection);
2661
2891
        g_rpc_connection = NULL;
2662
2892
  }
2663
2893
 
2708
2938
        g_plugin.description = NULL;
2709
2939
  }
2710
2940
}
 
2941
 
 
2942
static NPError plugin_restart(void)
 
2943
{
 
2944
  if (g_plugin.is_wrapper)
 
2945
        return NPERR_NO_ERROR;
 
2946
 
 
2947
  // Shut it down    
 
2948
  plugin_exit();
 
2949
  g_plugin.initialized = 0;
 
2950
  g_plugin.viewer_pid = -1;
 
2951
  g_plugin.is_wrapper = 0;
 
2952
 
 
2953
  // And start it again
 
2954
  plugin_init(1);
 
2955
  if (g_plugin.initialized <= 0)
 
2956
        return NPERR_MODULE_LOAD_FAILED_ERROR;
 
2957
 
 
2958
  return invoke_NP_Initialize(npapi_version);
 
2959
}
 
2960
 
 
2961
static NPError plugin_restart_if_needed(void)
 
2962
{
 
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;
 
2968
        last_restart = now;
 
2969
 
 
2970
        D(bug("Restart plugins viewer\n"));
 
2971
        NPError ret = plugin_restart();
 
2972
        D(bug(" return: %d [%s]\n", ret, string_of_NPError(ret)));
 
2973
        return ret;
 
2974
  }
 
2975
 
 
2976
  return NPERR_NO_ERROR;
 
2977
}