3
This is an encapsulation of the Netscape plugin API.
6
Copyright (c) 2000 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
7
Stefan Schimanski <1Stein@gmx.de>
8
2003-2005 George Staikos <staikos@kde.org>
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 2 of the License, or
13
(at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program; if not, write to the Free Software
22
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27
#include "NSPluginCallbackIface_stub.h"
46
#include <dcopclient.h>
50
#include <kio/netaccess.h>
51
#include <klibloader.h>
54
#include <kprotocolmanager.h>
55
#include <kstandarddirs.h>
56
#include <ktempfile.h>
59
#include <X11/Intrinsic.h>
60
#include <X11/Composite.h>
61
#include <X11/Constraint.h>
62
#include <X11/Shell.h>
63
#include <X11/StringDefs.h>
65
// provide these symbols when compiling with gcc 3.x
67
#if defined __GNUC__ && defined __GNUC_MINOR__
68
# define KDE_GNUC_PREREQ(maj, min) \
69
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
71
# define KDE_GNUC_PREREQ(maj, min) 0
75
#if defined(__GNUC__) && KDE_GNUC_PREREQ(3,0)
76
extern "C" void* __builtin_new(size_t s)
78
return operator new(s);
81
extern "C" void __builtin_delete(void* p)
86
extern "C" void* __builtin_vec_new(size_t s)
88
return operator new[](s);
91
extern "C" void __builtin_vec_delete(void* p)
96
extern "C" void __pure_virtual()
102
// server side functions -----------------------------------------------------
105
void *g_NPN_MemAlloc(uint32 size)
107
void *mem = ::malloc(size);
109
//kdDebug(1431) << "g_NPN_MemAlloc(), size=" << size << " allocated at " << mem << endl;
116
void g_NPN_MemFree(void *ptr)
118
//kdDebug(1431) << "g_NPN_MemFree() at " << ptr << endl;
123
uint32 g_NPN_MemFlush(uint32 size)
126
//kdDebug(1431) << "g_NPN_MemFlush()" << endl;
127
// MAC OS only.. we don't use this
133
void g_NPN_ForceRedraw(NPP /*instance*/)
135
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api3.html#999401
137
kdDebug(1431) << "g_NPN_ForceRedraw() [unimplemented]" << endl;
142
void g_NPN_InvalidateRect(NPP /*instance*/, NPRect* /*invalidRect*/)
144
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api7.html#999503
146
kdDebug(1431) << "g_NPN_InvalidateRect() [unimplemented]" << endl;
151
void g_NPN_InvalidateRegion(NPP /*instance*/, NPRegion /*invalidRegion*/)
153
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api8.html#999528
155
kdDebug(1431) << "g_NPN_InvalidateRegion() [unimplemented]" << endl;
160
NPError g_NPN_GetValue(NPP /*instance*/, NPNVariable variable, void *value)
162
kdDebug(1431) << "g_NPN_GetValue(), variable=" << static_cast<int>(variable) << endl;
167
*(void**)value = qt_xdisplay();
168
return NPERR_NO_ERROR;
169
case NPNVxtAppContext:
170
*(void**)value = XtDisplayToApplicationContext(qt_xdisplay());
171
return NPERR_NO_ERROR;
172
case NPNVjavascriptEnabledBool:
173
*(bool*)value = true;
174
return NPERR_NO_ERROR;
175
case NPNVasdEnabledBool:
176
// SmartUpdate - we don't do this
177
*(bool*)value = false;
178
return NPERR_NO_ERROR;
179
case NPNVisOfflineBool:
180
// Offline browsing - no thanks
181
*(bool*)value = false;
182
return NPERR_NO_ERROR;
184
*(NPNToolkitType*)value = NPNVGtk2;
185
return NPERR_NO_ERROR;
186
case NPNVSupportsXEmbedBool:
187
*(bool*)value = true;
188
return NPERR_NO_ERROR;
190
return NPERR_INVALID_PARAM;
195
NPError g_NPN_DestroyStream(NPP instance, NPStream* stream,
198
// FIXME: is this correct? I imagine it is not. (GS)
199
kdDebug(1431) << "g_NPN_DestroyStream()" << endl;
201
NSPluginInstance *inst = (NSPluginInstance*) instance->ndata;
202
inst->streamFinished( (NSPluginStream *)stream->ndata );
206
return NPERR_NO_ERROR;
207
case NPRES_USER_BREAK:
208
// FIXME: notify the user
209
case NPRES_NETWORK_ERR:
210
// FIXME: notify the user
212
return NPERR_GENERIC_ERROR;
217
NPError g_NPN_RequestRead(NPStream* /*stream*/, NPByteRange* /*rangeList*/)
219
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api16.html#999734
220
kdDebug(1431) << "g_NPN_RequestRead() [unimplemented]" << endl;
223
return NPERR_GENERIC_ERROR;
226
NPError g_NPN_NewStream(NPP /*instance*/, NPMIMEType /*type*/,
227
const char* /*target*/, NPStream** /*stream*/)
229
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api12.html#999628
230
kdDebug(1431) << "g_NPN_NewStream() [unimplemented]" << endl;
233
// This creates a stream from the plugin to the browser of type "type" to
234
// display in "target"
235
return NPERR_GENERIC_ERROR;
238
int32 g_NPN_Write(NPP /*instance*/, NPStream* /*stream*/, int32 /*len*/, void* /*buf*/)
240
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api21.html#999859
241
kdDebug(1431) << "g_NPN_Write() [unimplemented]" << endl;
249
NPError g_NPN_GetURL(NPP instance, const char *url, const char *target)
251
kdDebug(1431) << "g_NPN_GetURL: url=" << url << " target=" << target << endl;
253
NSPluginInstance *inst = static_cast<NSPluginInstance*>(instance->ndata);
255
inst->requestURL( QString::fromLatin1(url), QString::null,
256
QString::fromLatin1(target), 0 );
259
return NPERR_NO_ERROR;
263
NPError g_NPN_GetURLNotify(NPP instance, const char *url, const char *target,
266
kdDebug(1431) << "g_NPN_GetURLNotify: url=" << url << " target=" << target << " inst=" << (void*)instance << endl;
267
NSPluginInstance *inst = static_cast<NSPluginInstance*>(instance->ndata);
269
kdDebug(1431) << "g_NPN_GetURLNotify: ndata=" << (void*)inst << endl;
270
inst->requestURL( QString::fromLatin1(url), QString::null,
271
QString::fromLatin1(target), notifyData, true );
274
return NPERR_NO_ERROR;
278
NPError g_NPN_PostURLNotify(NPP instance, const char* url, const char* target,
279
uint32 len, const char* buf, NPBool file, void* notifyData)
281
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api14.html
282
kdDebug(1431) << "g_NPN_PostURLNotify() [incomplete]" << endl;
283
kdDebug(1431) << "url=[" << url << "] target=[" << target << "]" << endl;
285
KParts::URLArgs args;
288
return NPERR_NO_DATA;
291
if (file) { // buf is a filename
293
if (!f.open(IO_ReadOnly)) {
294
return NPERR_FILE_NOT_FOUND;
297
// FIXME: this will not work because we need to strip the header out!
298
postdata = f.readAll();
300
} else { // buf is raw data
301
// First strip out the header
302
const char *previousStart = buf;
304
bool previousCR = true;
311
if (buf[l-1] == '\n' || (previousCR && buf[l-1] == '\r')) {
312
if (previousCR) { // header is done!
313
if ((buf[l-1] == '\r' && buf[l] == '\n') ||
314
(buf[l-1] == '\n' && buf[l] == '\r'))
317
previousStart = &buf[l-1];
321
QString thisLine = QString::fromLatin1(previousStart, &buf[l-1] - previousStart).stripWhiteSpace();
323
previousStart = &buf[l];
326
kdDebug(1431) << "Found header line: [" << thisLine << "]" << endl;
327
if (thisLine.startsWith("Content-Type: ")) {
328
args.setContentType(thisLine);
335
postdata.duplicate(previousStart, len - l + 1);
338
kdDebug(1431) << "Post data: " << postdata.size() << " bytes" << endl;
340
QFile f("/tmp/nspostdata");
341
f.open(IO_WriteOnly);
342
f.writeBlock(postdata);
346
if (!target || !*target) {
347
// Send the results of the post to the plugin
348
// (works by default)
349
} else if (!strcmp(target, "_current") || !strcmp(target, "_self") ||
350
!strcmp(target, "_top")) {
351
// Unload the plugin, put the results in the frame/window that the
352
// plugin was loaded in
354
} else if (!strcmp(target, "_new") || !strcmp(target, "_blank")){
355
// Open a new browser window and write the results there
358
// Write the results to the specified frame
362
NSPluginInstance *inst = static_cast<NSPluginInstance*>(instance->ndata);
363
if (inst && !inst->normalizedURL(QString::fromLatin1(url)).isNull()) {
364
inst->postURL( QString::fromLatin1(url), postdata, args.contentType(),
365
QString::fromLatin1(target), notifyData, args, true );
367
// Unsupported / insecure
368
return NPERR_INVALID_URL;
371
return NPERR_NO_ERROR;
375
NPError g_NPN_PostURL(NPP instance, const char* url, const char* target,
376
uint32 len, const char* buf, NPBool file)
378
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api13.html
379
kdDebug(1431) << "g_NPN_PostURL()" << endl;
380
kdDebug(1431) << "url=[" << url << "] target=[" << target << "]" << endl;
382
KParts::URLArgs args;
385
return NPERR_NO_DATA;
388
if (file) { // buf is a filename
390
if (!f.open(IO_ReadOnly)) {
391
return NPERR_FILE_NOT_FOUND;
394
// FIXME: this will not work because we need to strip the header out!
395
postdata = f.readAll();
397
} else { // buf is raw data
398
// First strip out the header
399
const char *previousStart = buf;
401
bool previousCR = true;
408
if (buf[l-1] == '\n' || (previousCR && buf[l-1] == '\r')) {
409
if (previousCR) { // header is done!
410
if ((buf[l-1] == '\r' && buf[l] == '\n') ||
411
(buf[l-1] == '\n' && buf[l] == '\r'))
414
previousStart = &buf[l-1];
418
QString thisLine = QString::fromLatin1(previousStart, &buf[l-1] - previousStart).stripWhiteSpace();
420
previousStart = &buf[l];
423
kdDebug(1431) << "Found header line: [" << thisLine << "]" << endl;
424
if (thisLine.startsWith("Content-Type: ")) {
425
args.setContentType(thisLine);
432
postdata.duplicate(previousStart, len - l + 1);
435
kdDebug(1431) << "Post data: " << postdata.size() << " bytes" << endl;
437
QFile f("/tmp/nspostdata");
438
f.open(IO_WriteOnly);
439
f.writeBlock(postdata);
443
if (!target || !*target) {
444
// Send the results of the post to the plugin
445
// (works by default)
446
} else if (!strcmp(target, "_current") || !strcmp(target, "_self") ||
447
!strcmp(target, "_top")) {
448
// Unload the plugin, put the results in the frame/window that the
449
// plugin was loaded in
451
} else if (!strcmp(target, "_new") || !strcmp(target, "_blank")){
452
// Open a new browser window and write the results there
455
// Write the results to the specified frame
459
NSPluginInstance *inst = static_cast<NSPluginInstance*>(instance->ndata);
460
if (inst && !inst->normalizedURL(QString::fromLatin1(url)).isNull()) {
461
inst->postURL( QString::fromLatin1(url), postdata, args.contentType(),
462
QString::fromLatin1(target), 0L, args, false );
464
// Unsupported / insecure
465
return NPERR_INVALID_URL;
468
return NPERR_NO_ERROR;
472
// display status message
473
void g_NPN_Status(NPP instance, const char *message)
475
kdDebug(1431) << "g_NPN_Status(): " << message << endl;
480
// turn into an instance signal
481
NSPluginInstance *inst = (NSPluginInstance*) instance->ndata;
483
inst->emitStatus(message);
487
// inquire user agent
488
const char *g_NPN_UserAgent(NPP /*instance*/)
490
KProtocolManager kpm;
491
QString agent = kpm.userAgentForHost("nspluginviewer");
492
kdDebug(1431) << "g_NPN_UserAgent() = " << agent << endl;
493
// flash crashes without Firefox UA
494
agent = "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.10) Gecko/2007101500 Firefox/2.0.0.10";
495
return agent.latin1();
499
// inquire version information
500
void g_NPN_Version(int *plugin_major, int *plugin_minor, int *browser_major, int *browser_minor)
502
kdDebug(1431) << "g_NPN_Version()" << endl;
504
// FIXME: Use the sensible values
505
*browser_major = NP_VERSION_MAJOR;
506
*browser_minor = NP_VERSION_MINOR;
508
*plugin_major = NP_VERSION_MAJOR;
509
*plugin_minor = NP_VERSION_MINOR;
513
void g_NPN_ReloadPlugins(NPBool reloadPages)
515
// http://devedge.netscape.com/library/manuals/2002/plugin/1.0/npn_api15.html#999713
516
kdDebug(1431) << "g_NPN_ReloadPlugins()" << endl;
518
p << KGlobal::dirs()->findExe("nspluginscan");
521
// This is the proper way, but it cannot be done because we have no
522
// handle to the caller! How stupid! We cannot force all konqi windows
523
// to reload - that would be evil.
524
//p.start(KProcess::Block);
525
// Let's only allow the caller to be reloaded, not everything.
527
// _callback->reloadPage();
528
p.start(KProcess::DontCare);
530
p.start(KProcess::DontCare);
536
JRIEnv *g_NPN_GetJavaEnv()
538
kdDebug(1431) << "g_NPN_GetJavaEnv() [unimplemented]" << endl;
539
// FIXME - what do these do? I can't find docs, and even Mozilla doesn't
545
jref g_NPN_GetJavaPeer(NPP /*instance*/)
547
kdDebug(1431) << "g_NPN_GetJavaPeer() [unimplemented]" << endl;
548
// FIXME - what do these do? I can't find docs, and even Mozilla doesn't
554
NPError g_NPN_SetValue(NPP /*instance*/, NPPVariable variable, void* /*value*/)
556
kdDebug(1431) << "g_NPN_SetValue() [unimplemented]" << endl;
558
case NPPVpluginWindowBool:
560
// If true, the plugin is windowless. If false, it is in a window.
561
case NPPVpluginTransparentBool:
563
// If true, the plugin is displayed transparent
565
return NPERR_GENERIC_ERROR;
573
/******************************************************************/
576
NSPluginInstance::forwarder(Widget w, XtPointer cl_data, XEvent * event, Boolean * cont)
579
NSPluginInstance *inst = (NSPluginInstance*)cl_data;
581
if (inst->_form == 0 || event->xkey.window == XtWindow(inst->_form))
584
event->xkey.window = XtWindow(inst->_form);
585
event->xkey.subwindow = None;
586
XtDispatchEvent(event);
590
NSPluginInstance::NSPluginInstance(NPP privateData, NPPluginFuncs *pluginFuncs,
591
KLibrary *handle, int width, int height,
592
QString src, QString /*mime*/,
593
QString appId, QString callbackId,
594
bool embed, WId xembed,
595
QObject *parent, const char* name )
596
: DCOPObject(), QObject( parent, name )
606
_tempFiles.setAutoDelete( true );
607
_streams.setAutoDelete( true );
608
_waitingRequests.setAutoDelete( true );
609
_callback = new NSPluginCallbackIface_stub( appId.latin1(), callbackId.latin1() );
610
_xembed_window = xembed;
611
_toplevel = _form = 0;
614
base.setFileName( QString::null );
615
_baseURL = base.url();
617
memcpy(&_pluginFuncs, pluginFuncs, sizeof(_pluginFuncs));
619
_timer = new QTimer( this );
620
connect( _timer, SIGNAL(timeout()), SLOT(timer()) );
622
kdDebug(1431) << "NSPluginInstance::NSPluginInstance" << endl;
623
kdDebug(1431) << "pdata = " << _npp->pdata << endl;
624
kdDebug(1431) << "ndata = " << _npp->ndata << endl;
632
if( _xembed_window == 0 ) {
633
// create drawing area
636
XtSetArg(args[nargs], XtNwidth, width); nargs++;
637
XtSetArg(args[nargs], XtNheight, height); nargs++;
638
XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
641
XtGetApplicationNameAndClass(qt_xdisplay(), &n, &c);
643
_toplevel = XtAppCreateShell("drawingArea", c, applicationShellWidgetClass,
644
qt_xdisplay(), args, nargs);
646
// What exactly does widget mapping mean? Without this call the widget isn't
647
// embedded correctly. With it the viewer doesn't show anything in standalone mode.
649
XtSetMappedWhenManaged(_toplevel, False);
650
XtRealizeWidget(_toplevel);
652
// Create form window that is searched for by flash plugin
653
_form = XtVaCreateWidget("form", compositeWidgetClass, _toplevel, NULL);
654
XtSetArg(args[nargs], XtNvisual, QPaintDevice::x11AppVisual()); nargs++;
655
XtSetArg(args[nargs], XtNdepth, QPaintDevice::x11AppDepth()); nargs++;
656
XtSetArg(args[nargs], XtNcolormap, QPaintDevice::x11AppColormap()); nargs++;
657
XtSetValues(_form, args, nargs);
658
XSync(qt_xdisplay(), false);
660
// From mozilla - not sure if it's needed yet, nor what to use for embedder
662
/* this little trick seems to finish initializing the widget */
663
#if XlibSpecificationRelease >= 6
664
XtRegisterDrawable(qt_xdisplay(), embedderid, _toplevel);
666
_XtRegisterWindow(embedderid, _toplevel);
669
XtRealizeWidget(_form);
670
XtManageChild(_form);
672
// Register forwarder
673
XtAddEventHandler(_toplevel, (KeyPressMask|KeyReleaseMask),
674
False, forwarder, (XtPointer)this );
675
XtAddEventHandler(_form, (KeyPressMask|KeyReleaseMask),
676
False, forwarder, (XtPointer)this );
677
XSync(qt_xdisplay(), false);
681
NSPluginInstance::~NSPluginInstance()
683
kdDebug(1431) << "-> ~NSPluginInstance" << endl;
685
kdDebug(1431) << "<- ~NSPluginInstance" << endl;
689
void NSPluginInstance::destroy()
693
kdDebug(1431) << "delete streams" << endl;
694
_waitingRequests.clear();
698
for( NSPluginStreamBase *s=_streams.first(); s!=0; ) {
699
NSPluginStreamBase *next = _streams.next();
706
kdDebug(1431) << "delete callbacks" << endl;
710
kdDebug(1431) << "destroy plugin" << endl;
711
NPSavedData *saved = 0;
713
// As of 7/31/01, nsplugin crashes when used with Qt
714
// linked with libGL if the destroy function is called.
715
// A patch on that date hacked out the following call.
716
// On 11/17/01, Jeremy White has reenabled this destroy
717
// in a an attempt to better understand why this crash
718
// occurs so that the real problem can be found and solved.
719
// It's possible that a flaw in the SetWindow call
720
// caused the crash and it is now fixed.
721
if ( _pluginFuncs.destroy )
722
_pluginFuncs.destroy( _npp, &saved );
724
if (saved && saved->len && saved->buf)
725
g_NPN_MemFree(saved->buf);
727
g_NPN_MemFree(saved);
730
XtRemoveEventHandler(_form, (KeyPressMask|KeyReleaseMask),
731
False, forwarder, (XtPointer)this);
732
XtRemoveEventHandler(_toplevel, (KeyPressMask|KeyReleaseMask),
733
False, forwarder, (XtPointer)this);
734
XtDestroyWidget(_form);
736
XtDestroyWidget(_toplevel);
741
::free(_npp); // matched with malloc() in newInstance
749
void NSPluginInstance::shutdown()
751
NSPluginClass *cls = dynamic_cast<NSPluginClass*>(parent());
754
cls->destroyInstance( this );
759
void NSPluginInstance::timer()
762
_timer->start( 100, true );
768
// start queued requests
769
kdDebug(1431) << "looking for waiting requests" << endl;
770
while ( _waitingRequests.head() ) {
771
kdDebug(1431) << "request found" << endl;
772
Request req( *_waitingRequests.head() );
773
_waitingRequests.remove();
778
if ( req.url.left(11).lower()=="javascript:" )
780
else if ( KURL::isRelativeURL(req.url) ) {
782
KURL absUrl( bu, req.url );
784
} else if ( req.url[0]=='/' && KURL(_baseURL).hasHost() ) {
785
KURL absUrl( _baseURL );
786
absUrl.setPath( req.url );
791
// non empty target = frame target
792
if ( !req.target.isEmpty())
797
_callback->postURL( url, req.target, req.data, req.mime );
799
_callback->requestURL( url, req.target );
802
NPURLNotify( req.url, NPRES_DONE, req.notify );
808
kdDebug(1431) << "Starting new stream " << req.url << endl;
812
NSPluginStream *s = new NSPluginStream( this );
813
connect( s, SIGNAL(finished(NSPluginStreamBase*)),
814
SLOT(streamFinished(NSPluginStreamBase*)) );
815
_streams.append( s );
817
kdDebug() << "posting to " << url << endl;
819
emitStatus( i18n("Submitting data to %1").arg(url) );
820
s->post( url, req.data, req.mime, req.notify, req.args );
821
} else if (url.lower().startsWith("javascript:")){
823
static Q_INT32 _jsrequestid = 0;
824
_jsrequests.insert(_jsrequestid, new Request(req));
825
_callback->evalJavaScript(_jsrequestid++, url.mid(11));
827
kdDebug() << "No callback for javascript: url!" << endl;
831
NSPluginStream *s = new NSPluginStream( this );
832
connect( s, SIGNAL(finished(NSPluginStreamBase*)),
833
SLOT(streamFinished(NSPluginStreamBase*)) );
834
_streams.append( s );
836
kdDebug() << "getting " << url << endl;
838
emitStatus( i18n("Requesting %1").arg(url) );
839
s->get( url, req.mime, req.notify, req.reload );
849
QString NSPluginInstance::normalizedURL(const QString& url) const {
852
KConfig cfg("kcmnspluginrc", true);
853
cfg.setGroup("Misc");
855
if (!cfg.readBoolEntry("HTTP URLs Only", false) ||
856
inURL.protocol() == "http" ||
857
inURL.protocol() == "https" ||
858
inURL.protocol() == "javascript") {
862
// Allow: javascript:, http, https, or no protocol (match loading)
863
kdDebug(1431) << "NSPluginInstance::normalizedURL - I don't think so. http or https only!" << endl;
864
return QString::null;
868
void NSPluginInstance::requestURL( const QString &url, const QString &mime,
869
const QString &target, void *notify, bool forceNotify, bool reload )
871
// Generally this should already be done, but let's be safe for now.
872
QString nurl = normalizedURL(url);
877
kdDebug(1431) << "NSPluginInstance::requestURL url=" << nurl << " target=" << target << " notify=" << notify << endl;
878
_waitingRequests.enqueue( new Request( nurl, mime, target, notify, forceNotify, reload ) );
879
_timer->start( 100, true );
883
void NSPluginInstance::postURL( const QString &url, const QByteArray& data,
885
const QString &target, void *notify,
886
const KParts::URLArgs& args, bool forceNotify )
888
// Generally this should already be done, but let's be safe for now.
889
QString nurl = normalizedURL(url);
894
kdDebug(1431) << "NSPluginInstance::postURL url=" << nurl << " target=" << target << " notify=" << notify << endl;
895
_waitingRequests.enqueue( new Request( nurl, data, mime, target, notify, args, forceNotify) );
896
_timer->start( 100, true );
900
void NSPluginInstance::emitStatus(const QString &message)
903
_callback->statusMessage( message );
907
void NSPluginInstance::streamFinished( NSPluginStreamBase* strm )
909
kdDebug(1431) << "-> NSPluginInstance::streamFinished" << endl;
910
emitStatus( QString::null );
911
_streams.setAutoDelete(false); // Don't delete it yet!! we get called from
913
_streams.remove(strm);
914
_streams.setAutoDelete(true);
916
_timer->start( 100, true );
919
int NSPluginInstance::setWindow(Q_INT8 remove)
924
return NPERR_NO_ERROR;
927
kdDebug(1431) << "-> NSPluginInstance::setWindow" << endl;
931
_win.height = _height;
933
_win.type = NPWindowTypeWindow;
935
// Well, the docu says sometimes, this is only used on the
936
// MAC, but sometimes it says it's always. Who knows...
937
_win.clipRect.top = 0;
938
_win.clipRect.left = 0;
939
_win.clipRect.bottom = _height;
940
_win.clipRect.right = _width;
942
if( _xembed_window ) {
943
_win.window = (void*) _xembed_window;
944
_win_info.type = NP_SETWINDOW;
945
_win_info.display = qt_xdisplay();
946
_win_info.visual = DefaultVisualOfScreen(DefaultScreenOfDisplay(qt_xdisplay()));
947
_win_info.colormap = DefaultColormapOfScreen(DefaultScreenOfDisplay(qt_xdisplay()));
948
_win_info.depth = DefaultDepthOfScreen(DefaultScreenOfDisplay(qt_xdisplay()));
950
_win.window = (void*) XtWindow(_form);
952
_win_info.type = NP_SETWINDOW;
953
_win_info.display = XtDisplay(_form);
954
_win_info.visual = DefaultVisualOfScreen(XtScreen(_form));
955
_win_info.colormap = DefaultColormapOfScreen(XtScreen(_form));
956
_win_info.depth = DefaultDepthOfScreen(XtScreen(_form));
959
kdDebug(1431) << "Window ID = " << _win.window << endl;
961
_win.ws_info = &_win_info;
963
NPError error = NPSetWindow( &_win );
965
kdDebug(1431) << "<- NSPluginInstance::setWindow = " << error << endl;
970
static void resizeWidgets(Window w, int width, int height) {
971
Window rroot, parent, *children;
972
unsigned int nchildren = 0;
974
if (XQueryTree(qt_xdisplay(), w, &rroot, &parent, &children, &nchildren)) {
975
for (unsigned int i = 0; i < nchildren; i++) {
976
XResizeWindow(qt_xdisplay(), children[i], width, height);
983
void NSPluginInstance::resizePlugin(Q_INT32 w, Q_INT32 h)
985
if (w == _width && h == _height)
988
kdDebug(1431) << "-> NSPluginInstance::resizePlugin( w=" << w << ", h=" << h << " ) " << endl;
994
XResizeWindow(qt_xdisplay(), XtWindow(_form), w, h);
995
XResizeWindow(qt_xdisplay(), XtWindow(_toplevel), w, h);
999
XtSetArg(args[nargs], XtNwidth, _width); nargs++;
1000
XtSetArg(args[nargs], XtNheight, _height); nargs++;
1001
XtSetArg(args[nargs], XtNvisual, QPaintDevice::x11AppVisual()); nargs++;
1002
XtSetArg(args[nargs], XtNdepth, QPaintDevice::x11AppDepth()); nargs++;
1003
XtSetArg(args[nargs], XtNcolormap, QPaintDevice::x11AppColormap()); nargs++;
1004
XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
1006
XtSetValues(_toplevel, args, nargs);
1007
XtSetValues(_form, args, nargs);
1009
resizeWidgets(XtWindow(_form), _width, _height);
1012
// If not visible yet, displayWindow() will call setWindow() again anyway, so avoid this.
1013
// This also handled plugins that are broken and cannot handle repeated setWindow() calls
1020
kdDebug(1431) << "<- NSPluginInstance::resizePlugin" << endl;
1024
void NSPluginInstance::javascriptResult(Q_INT32 id, QString result) {
1025
QMap<int, Request*>::iterator i = _jsrequests.find( id );
1026
if (i != _jsrequests.end()) {
1027
Request *req = i.data();
1028
_jsrequests.remove( i );
1029
NSPluginStream *s = new NSPluginStream( this );
1030
connect( s, SIGNAL(finished(NSPluginStreamBase*)),
1031
SLOT(streamFinished(NSPluginStreamBase*)) );
1032
_streams.append( s );
1034
int len = result.length();
1035
s->create( req->url, QString("text/plain"), req->notify, req->forceNotify );
1036
kdDebug(1431) << "javascriptResult has been called with: "<<result<<endl;
1038
QByteArray data(len + 1);
1039
memcpy(data.data(), result.latin1(), len);
1041
s->process(data, 0);
1043
len = 7; // "unknown"
1044
QByteArray data(len + 1);
1045
memcpy(data.data(), "unknown", len);
1047
s->process(data, 0);
1056
NPError NSPluginInstance::NPGetValue(NPPVariable variable, void *value)
1059
kdDebug() << "FIXME: value==0 in NSPluginInstance::NPGetValue" << endl;
1060
return NPERR_GENERIC_ERROR;
1063
if (!_pluginFuncs.getvalue)
1064
return NPERR_GENERIC_ERROR;
1066
NPError error = _pluginFuncs.getvalue(_npp, variable, value);
1068
CHECK(GetValue,error);
1072
NPError NSPluginInstance::NPSetValue(NPNVariable variable, void *value)
1075
kdDebug() << "FIXME: value==0 in NSPluginInstance::NPSetValue" << endl;
1076
return NPERR_GENERIC_ERROR;
1079
if (!_pluginFuncs.setvalue)
1080
return NPERR_GENERIC_ERROR;
1082
NPError error = _pluginFuncs.setvalue(_npp, variable, value);
1084
CHECK(SetValue,error);
1088
NPError NSPluginInstance::NPSetWindow(NPWindow *window)
1091
kdDebug() << "FIXME: window==0 in NSPluginInstance::NPSetWindow" << endl;
1092
return NPERR_GENERIC_ERROR;
1095
if (!_pluginFuncs.setwindow)
1096
return NPERR_GENERIC_ERROR;
1098
NPError error = _pluginFuncs.setwindow(_npp, window);
1100
CHECK(SetWindow,error);
1104
NPError NSPluginInstance::NPDestroyStream(NPStream *stream, NPReason reason)
1107
kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPDestroyStream" << endl;
1108
return NPERR_GENERIC_ERROR;
1111
if (!_pluginFuncs.destroystream)
1112
return NPERR_GENERIC_ERROR;
1114
NPError error = _pluginFuncs.destroystream(_npp, stream, reason);
1116
CHECK(DestroyStream,error);
1120
NPError NSPluginInstance::NPNewStream(NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype)
1123
kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPNewStream" << endl;
1124
return NPERR_GENERIC_ERROR;
1128
kdDebug() << "FIXME: stype==0 in NSPluginInstance::NPNewStream" << endl;
1129
return NPERR_GENERIC_ERROR;
1132
if (!_pluginFuncs.newstream)
1133
return NPERR_GENERIC_ERROR;
1135
NPError error = _pluginFuncs.newstream(_npp, type, stream, seekable, stype);
1137
CHECK(NewStream,error);
1141
void NSPluginInstance::NPStreamAsFile(NPStream *stream, const char *fname)
1144
kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPStreamAsFile" << endl;
1149
kdDebug() << "FIXME: fname==0 in NSPluginInstance::NPStreamAsFile" << endl;
1153
if (!_pluginFuncs.asfile)
1156
_pluginFuncs.asfile(_npp, stream, fname);
1160
int32 NSPluginInstance::NPWrite(NPStream *stream, int32 offset, int32 len, void *buf)
1163
kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPWrite" << endl;
1168
kdDebug() << "FIXME: buf==0 in NSPluginInstance::NPWrite" << endl;
1172
if (!_pluginFuncs.write)
1175
return _pluginFuncs.write(_npp, stream, offset, len, buf);
1179
int32 NSPluginInstance::NPWriteReady(NPStream *stream)
1182
kdDebug() << "FIXME: stream==0 in NSPluginInstance::NPWriteReady" << endl;
1186
if (!_pluginFuncs.writeready)
1189
return _pluginFuncs.writeready(_npp, stream);
1193
void NSPluginInstance::NPURLNotify(QString url, NPReason reason, void *notifyData)
1195
if (!_pluginFuncs.urlnotify)
1198
_pluginFuncs.urlnotify(_npp, url.ascii(), reason, notifyData);
1202
void NSPluginInstance::addTempFile(KTempFile *tmpFile)
1204
_tempFiles.append(tmpFile);
1208
* We have to call this after we reparent the widget otherwise some plugins
1209
* like the ones based on WINE get very confused. (their coordinates are not
1210
* adjusted for the mouse at best)
1212
void NSPluginInstance::displayPlugin()
1218
kdDebug(1431) << "<- NSPluginInstance::displayPlugin = " << (void*)this << endl;
1221
static bool has_focus = false;
1223
void NSPluginInstance::gotFocusIn()
1228
void NSPluginInstance::gotFocusOut()
1234
// Prevent plugins from polling the keyboard regardless of focus.
1235
static int (*real_xquerykeymap)( Display*, char[32] ) = NULL;
1237
extern "C" KDE_EXPORT
1238
int XQueryKeymap( Display* dpy, char k[32] )
1240
if( real_xquerykeymap == NULL )
1241
real_xquerykeymap = (int (*)( Display*, char[32] )) dlsym( RTLD_NEXT, "XQueryKeymap" );
1243
return real_xquerykeymap( dpy, k );
1250
/***************************************************************************/
1252
NSPluginViewer::NSPluginViewer( QCString dcopId,
1253
QObject *parent, const char *name )
1254
: DCOPObject(dcopId), QObject( parent, name )
1256
_classes.setAutoDelete( true );
1257
connect(KApplication::dcopClient(),
1258
SIGNAL(applicationRemoved(const QCString&)),
1260
SLOT(appUnregistered(const QCString&)));
1264
NSPluginViewer::~NSPluginViewer()
1266
kdDebug(1431) << "NSPluginViewer::~NSPluginViewer" << endl;
1270
void NSPluginViewer::appUnregistered(const QCString& id) {
1275
QDictIterator<NSPluginClass> it(_classes);
1277
while ( (c = it.current()) ) {
1278
QString key = it.currentKey();
1280
if (c->app() == id) {
1281
_classes.remove(key);
1285
if (_classes.isEmpty()) {
1291
void NSPluginViewer::shutdown()
1293
kdDebug(1431) << "NSPluginViewer::shutdown" << endl;
1295
#if QT_VERSION < 0x030100
1303
DCOPRef NSPluginViewer::newClass( QString plugin )
1305
kdDebug(1431) << "NSPluginViewer::NewClass( " << plugin << ")" << endl;
1307
// search existing class
1308
NSPluginClass *cls = _classes[ plugin ];
1311
cls = new NSPluginClass( plugin, this );
1313
DCOPClient *dc = callingDcopClient();
1315
id = dc->senderId();
1318
if ( cls->error() ) {
1319
kdError(1431) << "Can't create plugin class" << endl;
1324
_classes.insert( plugin, cls );
1327
return DCOPRef( kapp->dcopClient()->appId(), cls->objId() );
1331
/****************************************************************************/
1334
NSPluginClass::NSPluginClass( const QString &library,
1335
QObject *parent, const char *name )
1336
: DCOPObject(), QObject( parent, name )
1338
// initialize members
1339
_handle = KLibLoader::self()->library(QFile::encodeName(library));
1341
_constructed = false;
1343
_instances.setAutoDelete( true );
1344
_NP_GetMIMEDescription = 0;
1348
_timer = new QTimer( this );
1349
connect( _timer, SIGNAL(timeout()), SLOT(timer()) );
1353
kdDebug(1431) << "Could not dlopen " << library << endl;
1357
// get exported lib functions
1358
_NP_GetMIMEDescription = (NP_GetMIMEDescriptionUPP *)_handle->symbol("NP_GetMIMEDescription");
1359
_NP_Initialize = (NP_InitializeUPP *)_handle->symbol("NP_Initialize");
1360
_NP_Shutdown = (NP_ShutdownUPP *)_handle->symbol("NP_Shutdown");
1362
// check for valid returned ptrs
1363
if (!_NP_GetMIMEDescription) {
1364
kdDebug(1431) << "Could not get symbol NP_GetMIMEDescription" << endl;
1368
if (!_NP_Initialize) {
1369
kdDebug(1431) << "Could not get symbol NP_Initialize" << endl;
1373
if (!_NP_Shutdown) {
1374
kdDebug(1431) << "Could not get symbol NP_Shutdown" << endl;
1378
// initialize plugin
1379
kdDebug(1431) << "Plugin library " << library << " loaded!" << endl;
1380
_constructed = true;
1381
_error = initialize()!=NPERR_NO_ERROR;
1385
NSPluginClass::~NSPluginClass()
1395
void NSPluginClass::timer()
1398
for ( NSPluginInstance *it=_trash.first(); it!=0; it=_trash.next() )
1399
_instances.remove(it);
1405
int NSPluginClass::initialize()
1407
kdDebug(1431) << "NSPluginClass::Initialize()" << endl;
1409
if ( !_constructed )
1410
return NPERR_GENERIC_ERROR;
1412
// initialize nescape exported functions
1413
memset(&_pluginFuncs, 0, sizeof(_pluginFuncs));
1414
memset(&_nsFuncs, 0, sizeof(_nsFuncs));
1416
_pluginFuncs.size = sizeof(_pluginFuncs);
1417
_nsFuncs.size = sizeof(_nsFuncs);
1418
_nsFuncs.version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
1419
_nsFuncs.geturl = g_NPN_GetURL;
1420
_nsFuncs.posturl = g_NPN_PostURL;
1421
_nsFuncs.requestread = g_NPN_RequestRead;
1422
_nsFuncs.newstream = g_NPN_NewStream;
1423
_nsFuncs.write = g_NPN_Write;
1424
_nsFuncs.destroystream = g_NPN_DestroyStream;
1425
_nsFuncs.status = g_NPN_Status;
1426
_nsFuncs.uagent = g_NPN_UserAgent;
1427
_nsFuncs.memalloc = g_NPN_MemAlloc;
1428
_nsFuncs.memfree = g_NPN_MemFree;
1429
_nsFuncs.memflush = g_NPN_MemFlush;
1430
_nsFuncs.reloadplugins = g_NPN_ReloadPlugins;
1431
_nsFuncs.getJavaEnv = g_NPN_GetJavaEnv;
1432
_nsFuncs.getJavaPeer = g_NPN_GetJavaPeer;
1433
_nsFuncs.geturlnotify = g_NPN_GetURLNotify;
1434
_nsFuncs.posturlnotify = g_NPN_PostURLNotify;
1435
_nsFuncs.getvalue = g_NPN_GetValue;
1436
_nsFuncs.setvalue = g_NPN_SetValue;
1437
_nsFuncs.invalidaterect = g_NPN_InvalidateRect;
1438
_nsFuncs.invalidateregion = g_NPN_InvalidateRegion;
1439
_nsFuncs.forceredraw = g_NPN_ForceRedraw;
1441
// initialize plugin
1442
NPError error = _NP_Initialize(&_nsFuncs, &_pluginFuncs);
1443
CHECK(Initialize,error);
1447
QString NSPluginClass::getMIMEDescription()
1449
return _NP_GetMIMEDescription();
1453
void NSPluginClass::shutdown()
1455
kdDebug(1431) << "NSPluginClass::shutdown error=" << _error << endl;
1456
if( _NP_Shutdown && !_error )
1461
DCOPRef NSPluginClass::newInstance( QString url, QString mimeType, Q_INT8 embed,
1462
QStringList argn, QStringList argv,
1463
QString appId, QString callbackId,
1464
Q_INT8 reload, Q_INT8 doPost, QByteArray postData, Q_UINT32 xembed )
1466
kdDebug(1431) << "-> NSPluginClass::NewInstance" << endl;
1468
if ( !_constructed )
1471
// copy parameters over
1472
unsigned int argc = argn.count();
1473
char **_argn = new char*[argc];
1474
char **_argv = new char*[argc];
1478
QString baseURL = url;
1480
for (unsigned int i=0; i<argc; i++)
1482
QCString encN = argn[i].utf8();
1483
QCString encV = argv[i].utf8();
1485
const char *n = encN;
1486
const char *v = encV;
1488
_argn[i] = strdup(n);
1489
_argv[i] = strdup(v);
1491
if (!strcasecmp(_argn[i], "WIDTH")) width = argv[i].toInt();
1492
if (!strcasecmp(_argn[i], "HEIGHT")) height = argv[i].toInt();
1493
if (!strcasecmp(_argn[i], "__KHTML__PLUGINBASEURL")) baseURL = _argv[i];
1494
kdDebug(1431) << "argn=" << _argn[i] << " argv=" << _argv[i] << endl;
1497
// create plugin instance
1499
strncpy(mime, mimeType.ascii(), 255);
1501
NPP npp = (NPP)malloc(sizeof(NPP_t)); // I think we should be using
1502
// malloc here, just to be safe,
1503
// since the nsplugin plays with
1505
memset(npp, 0, sizeof(NPP_t));
1508
// create plugin instance
1509
NPError error = _pluginFuncs.newp(mime, npp, embed ? NP_EMBED : NP_FULL,
1510
argc, _argn, _argv, 0);
1511
kdDebug(1431) << "NPP_New = " << (int)error << endl;
1513
// don't use bool here, it can be 1 byte, but some plugins write it as int, and I can't find what the spec says
1514
int wants_xembed = false;
1515
if (_pluginFuncs.getvalue) {
1516
NPError error = _pluginFuncs.getvalue(npp, (NPPVariable)14/*NPPVpluginNeedsXEmbed*/, &wants_xembed );
1517
if( error != NPERR_NO_ERROR )
1518
wants_xembed = false;
1520
kdDebug(1431) << "Plugin requires XEmbed:" << (bool)wants_xembed << endl;
1522
// Create plugin instance object
1523
NSPluginInstance *inst = new NSPluginInstance( npp, &_pluginFuncs, _handle,
1524
width, height, baseURL, mimeType,
1525
appId, callbackId, embed, wants_xembed ? xembed : 0, this );
1527
// free arrays with arguments
1532
if ( error!=NPERR_NO_ERROR)
1535
//delete npp; double delete!
1536
kdDebug(1431) << "<- PluginClass::NewInstance = 0" << endl;
1540
// create source stream
1541
if ( !src.isEmpty() ) {
1543
inst->postURL(src, postData, mimeType, QString::null, 0, KParts::URLArgs(), false);
1545
inst->requestURL( src, mimeType, QString::null, 0, false, reload );
1549
_instances.append( inst );
1550
return DCOPRef(kapp->dcopClient()->appId(), inst->objId());
1554
void NSPluginClass::destroyInstance( NSPluginInstance* inst )
1556
// mark for destruction
1557
_trash.append( inst );
1558
timer(); //_timer->start( 0, TRUE );
1561
/****************************************************************************/
1563
NSPluginStreamBase::NSPluginStreamBase( NSPluginInstance *instance )
1564
: QObject( instance ), _instance(instance), _stream(0), _tempFile(0L),
1565
_pos(0), _queue(0), _queuePos(0), _error(false)
1571
NSPluginStreamBase::~NSPluginStreamBase()
1574
_instance->NPDestroyStream( _stream, NPRES_USER_BREAK );
1575
if (_stream && _stream->url)
1576
free(const_cast<char*>(_stream->url));
1586
void NSPluginStreamBase::stop()
1591
void NSPluginStreamBase::inform()
1600
// inform the plugin
1601
_instance->NPNewStream( _mimeType.isEmpty() ? (char *) "text/plain" : (char*)_mimeType.ascii(),
1602
_stream, false, &_streamType );
1603
kdDebug(1431) << "NewStream stype=" << _streamType << " url=" << _url << " mime=" << _mimeType << endl;
1605
// prepare data transfer
1608
if ( _streamType==NP_ASFILE || _streamType==NP_ASFILEONLY ) {
1609
_onlyAsFile = _streamType==NP_ASFILEONLY;
1610
if ( KURL(_url).isLocalFile() ) {
1611
kdDebug(1431) << "local file" << endl;
1612
// local file can be passed directly
1613
_fileURL = KURL(_url).path();
1615
// without streaming stream is finished already
1616
if ( _onlyAsFile ) {
1617
kdDebug() << "local file AS_FILE_ONLY" << endl;
1621
kdDebug() << "remote file" << endl;
1623
// stream into temporary file (use lower() in case the
1624
// filename as an upper case X in it)
1625
_tempFile = new KTempFile;
1626
_tempFile->setAutoDelete( TRUE );
1627
_fileURL = _tempFile->name();
1628
kdDebug() << "saving into " << _fileURL << endl;
1635
bool NSPluginStreamBase::create( const QString& url, const QString& mimeType, void *notify, bool forceNotify)
1641
_notifyData = notify;
1644
_onlyAsFile = false;
1645
_streamType = NP_NORMAL;
1647
_forceNotify = forceNotify;
1649
// create new stream
1650
_stream = new NPStream;
1651
_stream->ndata = this;
1652
_stream->url = strdup(url.ascii());
1655
_stream->lastmodified = 0;
1656
_stream->notifyData = _notifyData;
1658
_mimeType = mimeType;
1663
void NSPluginStreamBase::updateURL( const KURL& newURL )
1666
free(const_cast<char*>(_stream->url));
1667
_stream->url = strdup(_url.url().ascii());
1670
int NSPluginStreamBase::process( const QByteArray &data, int start )
1672
int32 max, sent, to_sent, len;
1673
char *d = data.data() + start;
1675
to_sent = data.size() - start;
1680
max = _instance->NPWriteReady(_stream);
1681
//kdDebug(1431) << "to_sent == " << to_sent << " and max = " << max << endl;
1682
len = QMIN(max, to_sent);
1684
//kdDebug(1431) << "-> Feeding stream to plugin: offset=" << _pos << ", len=" << len << endl;
1685
sent = _instance->NPWrite( _stream, _pos, len, d );
1686
//kdDebug(1431) << "<- Feeding stream: sent = " << sent << endl;
1688
if (sent == 0) // interrupt the stream for a few ms
1692
// stream data rejected/error
1693
kdDebug(1431) << "stream data rejected/error" << endl;
1699
_tempFile->dataStream()->writeRawBytes(d, sent);
1707
return data.size() - to_sent;
1711
bool NSPluginStreamBase::pump()
1713
//kdDebug(1431) << "queue pos " << _queuePos << ", size " << _queue.size() << endl;
1717
if ( _queuePos<_queue.size() ) {
1720
// handle AS_FILE_ONLY streams
1721
if ( _onlyAsFile ) {
1723
_tempFile->dataStream()->writeRawBytes( _queue, _queue.size() );
1725
newPos = _queuePos+_queue.size();
1728
newPos = process( _queue, _queuePos );
1732
if ( newPos==_queuePos )
1740
// return true if queue finished
1741
return _queuePos>=_queue.size();
1745
void NSPluginStreamBase::queue( const QByteArray &data )
1753
kdDebug(1431) << "new queue size=" << data.size()
1754
<< " data=" << (void*)data.data()
1755
<< " queue=" << (void*)_queue.data() << " qsize="
1756
<< _queue.size() << endl;
1761
void NSPluginStreamBase::finish( bool err )
1763
kdDebug(1431) << "finish error=" << err << endl;
1774
_instance->addTempFile( _tempFile );
1778
if ( !_fileURL.isEmpty() ) {
1779
kdDebug() << "stream as file " << _fileURL << endl;
1780
_instance->NPStreamAsFile( _stream, _fileURL.ascii() );
1783
_instance->NPDestroyStream( _stream, NPRES_DONE );
1784
if (_notifyData || _forceNotify)
1785
_instance->NPURLNotify( _url.url(), NPRES_DONE, _notifyData );
1793
_instance->NPDestroyStream( _stream, NPRES_NETWORK_ERR );
1794
if (_notifyData || _forceNotify)
1795
_instance->NPURLNotify( _url.url(), NPRES_NETWORK_ERR, _notifyData );
1799
if (_stream && _stream->url)
1800
free(const_cast<char *>(_stream->url));
1804
// destroy NSPluginStream object
1805
emit finished( this );
1809
/****************************************************************************/
1811
NSPluginBufStream::NSPluginBufStream( class NSPluginInstance *instance )
1812
: NSPluginStreamBase( instance )
1814
_timer = new QTimer( this );
1815
connect( _timer, SIGNAL(timeout()), this, SLOT(timer()) );
1819
NSPluginBufStream::~NSPluginBufStream()
1825
bool NSPluginBufStream::get( const QString& url, const QString& mimeType,
1826
const QByteArray &buf, void *notifyData,
1829
_singleShot = singleShot;
1830
if ( create( url, mimeType, notifyData ) ) {
1832
_timer->start( 100, true );
1839
void NSPluginBufStream::timer()
1841
bool finished = pump();
1846
if ( !finished && tries()<=8 )
1847
_timer->start( 100, true );
1849
finish( error() || tries()>8 );
1855
/****************************************************************************/
1857
NSPluginStream::NSPluginStream( NSPluginInstance *instance )
1858
: NSPluginStreamBase( instance ), _job(0)
1860
_resumeTimer = new QTimer( this );
1861
connect(_resumeTimer, SIGNAL(timeout()), this, SLOT(resume()));
1865
NSPluginStream::~NSPluginStream()
1872
bool NSPluginStream::get( const QString& url, const QString& mimeType,
1873
void *notify, bool reload )
1875
// create new stream
1876
if ( create( url, mimeType, notify ) ) {
1877
// start the kio job
1878
_job = KIO::get(KURL( url ), false, false);
1879
_job->addMetaData("errorPage", "false");
1880
_job->addMetaData("AllowCompressedPage", "false");
1882
_job->addMetaData("cache", "reload");
1884
connect(_job, SIGNAL(data(KIO::Job *, const QByteArray &)),
1885
SLOT(data(KIO::Job *, const QByteArray &)));
1886
connect(_job, SIGNAL(result(KIO::Job *)), SLOT(result(KIO::Job *)));
1887
connect(_job, SIGNAL(totalSize(KIO::Job *, KIO::filesize_t )),
1888
SLOT(totalSize(KIO::Job *, KIO::filesize_t)));
1889
connect(_job, SIGNAL(mimetype(KIO::Job *, const QString &)),
1890
SLOT(mimetype(KIO::Job *, const QString &)));
1891
connect(_job, SIGNAL(redirection(KIO::Job *, const KURL&)),
1892
SLOT(redirection(KIO::Job *, const KURL&)));
1899
bool NSPluginStream::post( const QString& url, const QByteArray& data,
1900
const QString& mimeType, void *notify, const KParts::URLArgs& args )
1902
// create new stream
1903
if ( create( url, mimeType, notify ) ) {
1904
// start the kio job
1905
_job = KIO::http_post(KURL( url ), data, false);
1906
_job->addMetaData("content-type", args.contentType());
1907
_job->addMetaData("errorPage", "false");
1908
_job->addMetaData("AllowCompressedPage", "false");
1909
connect(_job, SIGNAL(data(KIO::Job *, const QByteArray &)),
1910
SLOT(data(KIO::Job *, const QByteArray &)));
1911
connect(_job, SIGNAL(result(KIO::Job *)), SLOT(result(KIO::Job *)));
1912
connect(_job, SIGNAL(totalSize(KIO::Job *, KIO::filesize_t )),
1913
SLOT(totalSize(KIO::Job *, KIO::filesize_t)));
1914
connect(_job, SIGNAL(mimetype(KIO::Job *, const QString &)),
1915
SLOT(mimetype(KIO::Job *, const QString &)));
1916
connect(_job, SIGNAL(redirection(KIO::Job *, const KURL&)),
1917
SLOT(redirection(KIO::Job *, const KURL&)));
1924
void NSPluginStream::data(KIO::Job * job, const QByteArray &data)
1926
//kdDebug(1431) << "NSPluginStream::data - job=" << (void*)job << " data size=" << data.size() << endl;
1930
_resumeTimer->start( 100, TRUE );
1934
void NSPluginStream::redirection(KIO::Job * /*job*/, const KURL& url)
1939
void NSPluginStream::totalSize(KIO::Job * job, KIO::filesize_t size)
1941
kdDebug(1431) << "NSPluginStream::totalSize - job=" << (void*)job << " size=" << KIO::number(size) << endl;
1942
_stream->end = size;
1945
void NSPluginStream::mimetype(KIO::Job * job, const QString &mimeType)
1947
kdDebug(1431) << "NSPluginStream::QByteArray - job=" << (void*)job << " mimeType=" << mimeType << endl;
1948
_mimeType = mimeType;
1954
void NSPluginStream::resume()
1956
if ( error() || tries()>8 ) {
1963
kdDebug(1431) << "resume job" << endl;
1966
kdDebug(1431) << "restart timer" << endl;
1967
_resumeTimer->start( 100, TRUE );
1972
void NSPluginStream::result(KIO::Job *job)
1974
int err = job->error();
1976
finish( err!=0 || error() );
1979
#include "nsplugin.moc"
1980
// vim: ts=4 sw=4 et