dolphin/nsplugins/plugin_part.cpp
Maks Orlovich 8c731bc1d4 automatically merged revision 768871:
Make flash embedding work much better..
- Make sure to give distinct callback objects distinct IDs, so they
talk to the proper KHTMLPart. Fixes only one flash object working per
window
- Rework the size/init heuristics yet again, following closer to Seli's code,
but instead of trying to count events, etc., just have the part
tell us when we were really resized, and qwidget isn't making up a random

svn path=/trunk/KDE/kdebase/apps/; revision=768880
2008-01-30 20:54:20 +00:00

387 lines
11 KiB
C++

/*
Netscape Plugin Loader KPart
Copyright (c) 2000 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
Stefan Schimanski <1Stein@gmx.de>
Copyright (c) 2002-2005 George Staikos <staikos@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "plugin_part.h"
#include "nspluginloader.h"
#include "callbackadaptor.h"
#include <kaboutdata.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kfiledialog.h>
#include <kio/netaccess.h>
#include <klocale.h>
#include <kparts/browserinterface.h>
#include <kparts/browserextension.h>
#include <QLabel>
class PluginBrowserExtension : public KParts::BrowserExtension
{
friend class PluginPart;
public:
PluginBrowserExtension( KParts::ReadOnlyPart *parent )
: KParts::BrowserExtension( parent ) {}
~PluginBrowserExtension() {}
// ATTENTION: you -CANNOT- add data members here
};
PluginLiveConnectExtension::PluginLiveConnectExtension(PluginPart* part)
: KParts::LiveConnectExtension(part), _part(part), _retval(0L) {
}
PluginLiveConnectExtension::~PluginLiveConnectExtension() {
}
bool PluginLiveConnectExtension::get(const unsigned long, const QString &field, Type &type, unsigned long &retobj, QString &value) {
Q_UNUSED(type);
Q_UNUSED(retobj);
Q_UNUSED(value);
kDebug(1432) << "PLUGIN:LiveConnect::get " << field;
return false;
}
bool PluginLiveConnectExtension::call(const unsigned long, const QString &func, const QStringList &args, Type &type, unsigned long &retobjid, QString &value) {
Q_UNUSED(type);
Q_UNUSED(retobjid);
Q_UNUSED(value);
kDebug(1432) << "PLUGIN:LiveConnect::call " << func << " args: " << args;
return false;
}
bool PluginLiveConnectExtension::put( const unsigned long, const QString &field, const QString &value) {
kDebug(1432) << "PLUGIN:LiveConnect::put " << field << " " << value;
if (_retval && field == "__nsplugin") {
*_retval = value;
return true;
} else if (field.toLower() == "src") {
_part->changeSrc(value);
return true;
}
return false;
}
QString PluginLiveConnectExtension::evalJavaScript( const QString & script )
{
kDebug(1432) << "PLUGIN:LiveConnect::evalJavaScript " << script;
ArgList args;
QString jscode;
jscode.sprintf("this.__nsplugin=eval(\"%s\")", qPrintable( QString(script).replace('\\', "\\\\").replace('"', "\\\"")));
//kDebug(1432) << "String is [" << jscode << "]";
args.push_back(qMakePair(KParts::LiveConnectExtension::TypeString, jscode));
QString nsplugin("Undefined");
_retval = &nsplugin;
emit partEvent(0, "eval", args);
_retval = 0L;
return nsplugin;
}
K_EXPORT_PLUGIN(PluginFactory)
/**
* We need one static instance of the factory for our C 'main'
* function
*/
KComponentData *PluginFactory::s_instance = 0L;
PluginFactory::PluginFactory()
{
kDebug(1432) << "PluginFactory::PluginFactory";
s_instance = 0;
// preload plugin loader
_loader = NSPluginLoader::instance();
}
PluginFactory::~PluginFactory()
{
kDebug(1432) << "PluginFactory::~PluginFactory";
_loader->release();
if (s_instance) {
delete s_instance;
s_instance = 0;
}
}
KParts::Part * PluginFactory::createPartObject(QWidget *parentWidget, QObject *parent,
const char *classname, const QStringList &args)
{
Q_UNUSED(classname)
kDebug(1432) << "PluginFactory::create";
KParts::Part *obj = new PluginPart(parentWidget, parent, args);
return obj;
}
const KComponentData &PluginFactory::componentData()
{
kDebug(1432) << "PluginFactory::instance";
if (!s_instance) {
KAboutData about("plugin", 0, ki18n("plugin"), "1.99");
s_instance = new KComponentData(about);
}
return *s_instance;
}
/**************************************************************************/
static int s_callBackObjectCounter;
PluginPart::PluginPart(QWidget *parentWidget, QObject *parent, const QStringList &args)
: KParts::ReadOnlyPart(parent), _widget(0), _args(args),
_destructed(0L)
{
callbackPath = QString::fromLatin1("/Callback") + QString::number(s_callBackObjectCounter);
++s_callBackObjectCounter;
(void) new CallBackAdaptor( this );
QDBusConnection::sessionBus().registerObject( callbackPath, this );
setComponentData(PluginFactory::componentData());
kDebug(1432) << "PluginPart::PluginPart";
// we have to keep the class name of KParts::PluginBrowserExtension
// to let khtml find it
_extension = static_cast<PluginBrowserExtension*>(new KParts::BrowserExtension(this));
_liveconnect = new PluginLiveConnectExtension(this);
// Only create this if we have no parent since the parent part is
// responsible for "Save As" then
if (!parent || !parent->inherits("Part")) {
KAction *action = actionCollection()->addAction("saveDocument");
action->setText(i18n("&Save As..."));
connect(action, SIGNAL(triggered(bool) ), SLOT(saveAs()));
action->setShortcut(Qt::CTRL+Qt::Key_S);
setXMLFile("nspluginpart.rc");
}
// create
_loader = NSPluginLoader::instance();
// create a canvas to insert our widget
_canvas = new PluginCanvasWidget( parentWidget );
//_canvas->setFocusPolicy( QWidget::ClickFocus );
_canvas->setFocusPolicy( Qt::WheelFocus );
setWidget(_canvas);
_canvas->show();
QObject::connect( _canvas, SIGNAL(resized(int,int)),
this, SLOT(pluginResized(int,int)) );
}
PluginPart::~PluginPart()
{
kDebug(1432) << "PluginPart::~PluginPart";
_loader->release();
if (_destructed)
*_destructed = true;
}
bool PluginPart::openUrl(const KUrl &url)
{
closeUrl();
kDebug(1432) << "-> PluginPart::openUrl";
setUrl(url);
QString surl = url.url();
QString smime = arguments().mimeType();
bool reload = arguments().reload();
bool embed = false;
// handle arguments
QStringList argn, argv;
QStringList::Iterator it = _args.begin();
for ( ; it != _args.end(); ) {
int equalPos = (*it).indexOf("=");
if (equalPos>0) {
QString name = (*it).left(equalPos).toUpper();
QString value = (*it).mid(equalPos+1);
if (value[0] == '"' && value[value.length()-1] == '"')
value = value.mid(1, value.length()-2);
kDebug(1432) << "name=" << name << " value=" << value;
if (!name.isEmpty()) {
// hack to pass view mode from khtml
if ( name=="__KHTML__PLUGINEMBED" ) {
embed = true;
kDebug(1432) << "__KHTML__PLUGINEMBED found";
} else {
argn << name;
argv << value;
}
}
}
it++;
}
if (surl.isEmpty()) {
kDebug(1432) << "<- PluginPart::openUrl - false (no url passed to nsplugin)";
return false;
}
// status messages
emit setWindowCaption( url.prettyUrl() );
emit setStatusBarText( i18n("Loading Netscape plugin for %1", url.prettyUrl()) );
// create plugin widget
NSPluginInstance *inst = _loader->newInstance( _canvas, surl, smime, embed,
argn, argv,
QDBusConnection::sessionBus().baseService(),
callbackPath, reload);
if ( inst ) {
_widget = inst;
_nspWidget = inst;
} else {
QLabel *label = new QLabel( i18n("Unable to load Netscape plugin for %1", url.url()), _canvas );
label->setAlignment( Qt::AlignCenter );
label->setWordWrap( true );
_widget = label;
}
_widget->resize(_canvas->width(), _canvas->height());
_widget->show();
kDebug(1432) << "<- PluginPart::openUrl = " << (inst!=0);
return inst != 0L;
}
bool PluginPart::closeUrl()
{
kDebug(1432) << "PluginPart::closeUrl";
delete _widget;
_widget = 0;
return true;
}
void PluginPart::reloadPage()
{
kDebug(1432) << "PluginPart::reloadPage()";
_extension->browserInterface()->callMethod("goHistory(int)", 0);
}
void PluginPart::postURL(const QString& url, const QString& target, const QByteArray& data, const QString& mime)
{
kDebug(1432) << "PluginPart::postURL( url=" << url
<< ", target=" << target << endl;
KUrl new_url(this->url(), url);
KParts::OpenUrlArguments arguments;
KParts::BrowserArguments browserArguments;
browserArguments.setDoPost(true);
browserArguments.frameName = target;
browserArguments.postData = data;
browserArguments.setContentType(mime);
emit _extension->openUrlRequest(new_url, arguments, browserArguments);
}
void PluginPart::requestURL(const QString& url, const QString& target)
{
kDebug(1432) << "PluginPart::requestURL( url=" << url
<< ", target=" << target << endl;
KUrl new_url(this->url(), url);
KParts::OpenUrlArguments arguments;
KParts::BrowserArguments browserArguments;
browserArguments.frameName = target;
browserArguments.setDoPost(false);
emit _extension->openUrlRequest(new_url, arguments, browserArguments);
}
void PluginPart::evalJavaScript(int id, const QString & script)
{
kDebug(1432) <<"evalJavascript: before widget check";
if (_widget) {
bool destructed = false;
_destructed = &destructed;
kDebug(1432) <<"evalJavascript: there is a widget:";
QString rc = _liveconnect->evalJavaScript(script);
if (destructed)
return;
_destructed = 0L;
kDebug(1432) << "Liveconnect: script [" << script << "] evaluated to [" << rc << "]";
NSPluginInstance *ni = dynamic_cast<NSPluginInstance*>(_widget.operator->());
if (ni)
ni->javascriptResult(id, rc);
}
}
void PluginPart::statusMessage(const QString &msg)
{
kDebug(1422) << "PluginPart::statusMessage " << msg;
emit setStatusBarText(msg);
}
void PluginPart::pluginResized(int w, int h)
{
if (_nspWidget)
_nspWidget->pluginResized(w, h);
if (_widget) {
_widget->resize(w, h);
}
}
void PluginPart::changeSrc(const QString& url) {
closeUrl();
openUrl(KUrl( url ));
}
void PluginPart::saveAs() {
KUrl savefile = KFileDialog::getSaveUrl(QString(), QString(), _widget);
KIO::NetAccess::file_copy(url(), savefile, _widget);
}
void PluginCanvasWidget::resizeEvent(QResizeEvent *ev)
{
QWidget::resizeEvent(ev);
emit resized(width(), height());
}
#include "plugin_part.moc"