1
/* sqUnixMozilla.c -- support for Squeak Netscape plugin
3
* Author: Bert Freudenberg <bert@isg.cs.uni-magdeburg.de>
5
* Last edited: 2007-09-07 13:53:35 by piumarta on emilia
7
* Originally based on Andreas Raab's sqWin32PluginSupport
9
* Notes: The plugin window handling stuff is in sqXWindow.c.
10
* browserProcessCommand() is called when data is available
18
#include <X11/Xatom.h>
24
#include "FilePlugin.h"
29
void DPRINT(char *format, ...)
33
debug= (NULL != getenv("NPSQUEAK_DEBUG"));
44
file= fopen("/tmp/npsqueak.log", "a+");
50
vfprintf(file, format, ap);
57
void DPRINT(char *format, ...) { }
60
/* from sqXWindow.c */
61
extern Display* stDisplay;
62
extern Window stWindow;
63
extern Window browserWindow;
64
extern Window stParent;
65
extern int browserPipes[2];
67
/* from interpret.c */
68
sqInt stackObjectValue(sqInt);
69
sqInt stackIntegerValue(sqInt);
71
sqInt byteSizeOf(sqInt);
72
void *firstIndexableField(sqInt);
75
sqInt positive32BitIntegerFor(sqInt);
76
sqInt nilObject(void);
77
sqInt instantiateClassindexableSize(sqInt, sqInt);
78
sqInt classByteArray(void);
80
sqInt pushBool(sqInt);
84
static void browserReceive(void *buf, size_t count);
85
static void browserSend(const void *buf, size_t count);
86
static void browserSendInt(int value);
87
static void browserReceiveData();
88
static void browserGetURLRequest(int id, char* url, int urlSize,
89
char* target, int targetSize);
90
static void browserPostURLRequest(int id, char* url, int urlSize,
91
char* target, int targetSize,
92
char* postData, int postDataSize);
94
typedef struct sqStreamRequest {
100
#define MAX_REQUESTS 128
102
#define SQUEAK_READ 0
103
#define SQUEAK_WRITE 1
106
(-1 != browserPipes[SQUEAK_READ])
108
#define CMD_BROWSER_WINDOW 1
109
#define CMD_GET_URL 2
110
#define CMD_POST_URL 3
111
#define CMD_RECEIVE_DATA 4
113
static sqStreamRequest *requests[MAX_REQUESTS];
117
/* primitives called from Squeak */
122
primitivePluginBrowserReady
123
Return true if a connection to the browser
124
has been established. Only necessary if some
125
sort of asynchronous communications are used.
127
int display_primitivePluginBrowserReady()
141
primitivePluginRequestUrlStream: url with: semaIndex
142
Request a URL from the browser. Signal semaIndex
143
when the result of the request can be queried.
144
Returns a handle used in subsequent calls to plugin
146
Note: A request id is the index into requests[].
148
int display_primitivePluginRequestURLStream()
150
sqStreamRequest *req;
151
int id, url, length, semaIndex;
153
if (!inBrowser) return primitiveFail();
155
DPRINT("VM: primitivePluginRequestURLStream()\n");
157
for (id=0; id<MAX_REQUESTS; id++) {
158
if (!requests[id]) break;
160
if (id >= MAX_REQUESTS) return primitiveFail();
162
semaIndex= stackIntegerValue(0);
163
url= stackObjectValue(1);
164
if (failed()) return 0;
166
if (!isBytes(url)) return primitiveFail();
168
req= calloc(1, sizeof(sqStreamRequest));
169
if (!req) return primitiveFail();
170
req->localName= NULL;
171
req->semaIndex= semaIndex;
175
length= byteSizeOf(url);
176
browserGetURLRequest(id, firstIndexableField(url), length, NULL, 0);
178
push(positive32BitIntegerFor(id));
179
DPRINT("VM: request id: %i\n", id);
185
primitivePluginRequestURL: url target: target semaIndex: semaIndex
186
Request a URL into the given target.
188
int display_primitivePluginRequestURL()
190
sqStreamRequest *req;
192
int target, targetLength;
195
if (!browserWindow) return primitiveFail();
196
for (id=0; id<MAX_REQUESTS; id++) {
197
if (!requests[id]) break;
200
if (id >= MAX_REQUESTS) return primitiveFail();
202
semaIndex= stackIntegerValue(0);
203
target= stackObjectValue(1);
204
url= stackObjectValue(2);
206
if (failed()) return 0;
207
if (!isBytes(url) || !isBytes(target)) return primitiveFail();
209
urlLength= byteSizeOf(url);
210
targetLength= byteSizeOf(target);
212
req= calloc(1, sizeof(sqStreamRequest));
213
if(!req) return primitiveFail();
214
req->localName= NULL;
215
req->semaIndex= semaIndex;
219
browserGetURLRequest(id, firstIndexableField(url), urlLength, firstIndexableField(target), targetLength);
221
push(positive32BitIntegerFor(id));
227
primitivePluginPostURL: url target: target data: data semaIndex: semaIndex
228
Post data to a URL into the given target.
230
int display_primitivePluginPostURL()
232
sqStreamRequest *req;
234
int target, targetLength;
235
int data, dataLength;
238
if (!browserWindow) return primitiveFail();
239
for (id=0; id<MAX_REQUESTS; id++) {
240
if (!requests[id]) break;
243
if (id >= MAX_REQUESTS) return primitiveFail();
245
semaIndex= stackIntegerValue(0);
246
data= stackObjectValue(1);
247
target= stackObjectValue(2);
248
url= stackObjectValue(3);
250
if (failed()) return 0;
251
if (target == nilObject()) target= 0;
252
if (!isBytes(url) || !isBytes(data) || !(!target || isBytes(target))) return primitiveFail();
254
urlLength= byteSizeOf(url);
255
targetLength= target ? byteSizeOf(target) : 0;
256
dataLength= byteSizeOf(data);
258
req= calloc(1, sizeof(sqStreamRequest));
259
if(!req) return primitiveFail();
260
req->localName= NULL;
261
req->semaIndex= semaIndex;
265
browserPostURLRequest(id, firstIndexableField(url), urlLength,
266
target ? firstIndexableField(target) : NULL, targetLength,
267
firstIndexableField(data), dataLength);
269
push(positive32BitIntegerFor(id));
274
primitivePluginRequestFileHandle: id
275
After a URL file request has been successfully
276
completed, return a file handle for the received
277
data. Note: The file handle must be read-only for
280
int display_primitivePluginRequestFileHandle()
282
sqStreamRequest *req;
286
id= stackIntegerValue(0);
287
if (failed()) return 0;
288
if (id < 0 || id >= MAX_REQUESTS) return primitiveFail();
291
if (!req || !req->localName) return primitiveFail();
293
fileOop= nilObject();
297
DPRINT("VM: Creating file handle for %s\n", req->localName);
299
openFn= ioLoadFunctionFrom("fileOpenNamesizewritesecure", "FilePlugin");
302
DPRINT("VM: Couldn't load fileOpenName:size:write:secure: from FilePlugin!\n");
303
return primitiveFail();
306
fileOop= ((sqInt (*)(char *, sqInt, sqInt, sqInt))openFn)
307
(req->localName, strlen(req->localName), 0 /* readonly */, 0 /* insecure */);
309
/* if file ends in a $, it was a temp link created by the plugin */
310
if ('$' == req->localName[strlen(req->localName) - 1])
312
DPRINT("VM: unlink %s\n", req->localName);
313
if (-1 == unlink(req->localName))
314
DPRINT("VM: unlink failed: %s\n", strerror(errno));
319
DPRINT("VM: file open failed\n");
330
primitivePluginDestroyRequest: id
331
Destroy a request that has been issued before.
333
sqInt display_primitivePluginDestroyRequest()
335
sqStreamRequest *req;
338
id= stackIntegerValue(0);
339
if (id < 0 || id >= MAX_REQUESTS) return primitiveFail();
342
if (req->localName) free(req->localName);
352
primitivePluginRequestState: id
353
Return true if the operation was successfully completed.
354
Return false if the operation was aborted.
355
Return nil if the operation is still in progress.
357
sqInt display_primitivePluginRequestState()
359
sqStreamRequest *req;
362
id= stackIntegerValue(0);
363
if (id < 0 || id >= MAX_REQUESTS) return primitiveFail();
365
if (!req) return primitiveFail();
367
if (req->state == -1) push(nilObject());
368
else pushBool(req->state);
374
/* helper functions */
376
static void browserReceive(void *buf, size_t count)
379
n= read(browserPipes[SQUEAK_READ], buf, count);
381
perror("Squeak read failed:");
383
fprintf(stderr, "Squeak read too few data from pipe\n");
387
static void browserSend(const void *buf, size_t count)
390
n= write(browserPipes[SQUEAK_WRITE], buf, count);
392
perror("Squeak plugin write failed:");
394
fprintf(stderr, "Squeak wrote too few data to pipe\n");
397
static void browserSendInt(int value)
399
browserSend(&value, 4);
405
Called in response to a CMD_RECEIVE_DATA message.
406
Retrieves the data file name and signals the semaphore.
408
static void browserReceiveData()
410
char *localName= NULL;
413
browserReceive(&id, 4);
414
browserReceive(&ok, 4);
416
DPRINT("VM: receiving data id: %i state %i\n", id, ok);
420
browserReceive(&length, 4);
422
localName= malloc(length+1);
423
browserReceive(localName, length);
424
localName[length]= 0;
425
DPRINT("VM: got filename %s\n", localName);
428
if (id >= 0 && id < MAX_REQUESTS) {
429
sqStreamRequest *req= requests[id];
431
req->localName= localName;
433
DPRINT("VM: signaling semaphore, state=%i\n", ok);
434
/* synchronizedSignalSemaphoreWithIndex(req->semaIndex);*/
435
signalSemaphoreWithIndex(req->semaIndex);
442
browserGetURLRequest:
443
Notify plugin to get the specified url into target
445
static void browserGetURLRequest(int id, char* url, int urlSize,
446
char* target, int targetSize)
449
fprintf(stderr, "Cannot submit URL request -- "
450
"there is no connection to a browser\n");
454
browserSendInt(CMD_GET_URL);
457
browserSendInt(urlSize);
459
browserSend(url, urlSize);
461
browserSendInt(targetSize);
463
browserSend(target, targetSize);
468
browserPostURLRequest:
469
Notify plugin to post data to the specified url and get result into target
471
static void browserPostURLRequest(int id, char* url, int urlSize,
472
char* target, int targetSize,
473
char* postData, int postDataSize)
476
fprintf(stderr, "Cannot submit URL post request -- "
477
"there is no connection to a browser\n");
481
browserSendInt(CMD_POST_URL);
484
browserSendInt(urlSize);
486
browserSend(url, urlSize);
488
browserSendInt(targetSize);
490
browserSend(target, targetSize);
492
browserSendInt(postDataSize);
493
if (postDataSize > 0)
494
browserSend(postData, postDataSize);
498
/***************************************************************
499
* Functions called from sqXWindow.c
500
***************************************************************/
503
browserProcessCommand:
504
Handle commands sent by the plugin.
506
void browserProcessCommand(void)
508
static int firstTime= 1;
514
/* enable non-blocking reads */
515
fcntl(browserPipes[SQUEAK_READ], F_SETFL, O_NONBLOCK);
517
DPRINT("VM: browserProcessCommand()\n");
519
n= read(browserPipes[SQUEAK_READ], &cmd, 4);
520
if (0 == n || (-1 == n && EAGAIN == errno))
525
case CMD_RECEIVE_DATA:
526
/* Data is coming in */
527
browserReceiveData();
529
case CMD_BROWSER_WINDOW:
530
/* Parent window has changed () */
531
browserReceive(&browserWindow, 4);
532
stParent= browserWindow;
533
DPRINT("VM: got browser window 0x%X\n", browserWindow);
536
fprintf(stderr, "Unknown command from Plugin: %i\n", cmd);
541
#else /* !defined(USE_X11) */
543
sqInt display_primitivePluginBrowserReady() { return primitiveFail(); }
544
sqInt display_primitivePluginRequestURLStream() { return primitiveFail(); }
545
sqInt display_primitivePluginRequestURL() { return primitiveFail(); }
546
sqInt display_primitivePluginPostURL() { return primitiveFail(); }
547
sqInt display_primitivePluginRequestFileHandle() { return primitiveFail(); }
548
sqInt display_primitivePluginDestroyRequest() { return primitiveFail(); }
549
sqInt display_primitivePluginRequestState() { return primitiveFail(); }