Qt Webkit中浏览器插件设计实现

移动开发
QtWebkit中插件可以有两种,一种Mime必须是application/x-qt-plugin或者application/x-qt-styled-widget,而另外一种则无需固定,可以是除了前面的两种以外任意其它Mime类型。

Qt Webkit浏览器插件设计实现是我们要介绍的内容,我们都知道浏览器中有一套由Netscape浏览器传承下来的插件接口,包括webkit,firefox都是支持的,但是那个开发起来比较困难,并且是平台相关的,借助于Qt的跨平台的特性,可以方便地为Qt开发出一套跨平台的插件

QtWebkit中插件可以有两种,一种Mime必须是application/x-qt-plugin或者application/x-qt-styled-widget,而另外一种则无需固定,可以是除了前面的两种以外任意其它Mime类型。

前一种相对来说开发起来比较容易,只需重新实现

QObject * QWebPage::createPlugin (   
const QString   
& classid, const QUrl   
& url, const QStringList   
& paramNames, const QStringList &paramValues   

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

这个函数即可,这个函数会把HTML文件中的参数都传递进来

下面是一个例子:

class PluginPage : public QWebPage  
{  
public:  
PluginPage(QObject *parent = 0)  
: QWebPage(parent) {}  
protected:  
virtual QObject *createPlugin(const QString &classid, const QUrl &url,  
const QStringList &paramNames,  
const QStringList &paramValues)  
{  
QObject *result = 0;  
if (classid == "pushbutton")  
result = new QPushButton();  
else if (classid == "lineedit")  
result = new QLineEdit();  
if (result)  
result->setObjectName(classid);  
//可以进行一些处理  
return result;  
}  
}; 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

这样下面的网页就可以一个pushbutton了:

<html> 
<body> 
<object type='application/x-qt-plugin' classid='pushbutton' id='mybutton'/> 
</body> 
</html> 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

并且还可以在JavaScript访问到QPushbutton,例如:

document.getElementById('mybutton').text将会返回按钮上的字符串。

前一节介绍的插件设计方式中虽然方便,但是其Mime类型只能是application/x-qt-plugin或者application/x-qt-styled-widget,这个有时候可能满足不了实际应用需求,那么另一种就没有这种限制,那可以是任意Mime类型的。这种设计需要重新实现QWebPluginFactory这个纯虚基类。先看看他的声明:

前一节介绍的插件设计方式中虽然方便,但是其Mime类型只能是application/x-qt-plugin或者application/x-qt-styled-widget,这个有时候可能满足不了实际应用需求,那么另一种就没有这种限制,那可以是任意Mime类型的。这种设计需要重新实现QWebPluginFactory这个纯虚基类。先看看他的声明:

class QWEBKIT_EXPORT QWebPluginFactory : public QObject {  
……  
public:  
struct Plugin {  
QString name;  
QString description;  
QList<MimeType> mimeTypes;  
};  
explicit QWebPluginFactory(QObject* parent = 0);  
virtual ~QWebPluginFactory();  
virtual QList<Plugin> plugins() const = 0;  
virtual void refreshPlugins();  
virtual QObject *create(const QString& mimeType,  
const QUrl&,  
const QStringList& argumentNames,  
const QStringList& argumentValues) const = 0;  
virtual bool extension(Extension extension, const ExtensionOption* option = 0, ExtensionReturn* output = 0);  
virtual bool supportsExtension(Extension extension) const;  
……  
}; 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

重点要实现的接口是plugins,用于获取plugin的列表,用于webkit内部判断该mime类型是否被支持,如果可以支持,那么就会调用create来创建这个插件,而具体打开哪个文件以及参数都会传递进来。

后两个extension和supportsExtension接口暂时没有发现有什么用处,暂不考虑。

因此重新实现的WebPluginFactory如下:

class WebPluginFactory: public QWebPluginFactory  
{  
    public:  
        WebPluginFactory(QObject *parent = 0);  
        ~WebPluginFactory(){};  
        QList<QWebPluginFactory::Plugin> plugins()const ;  
        void refreshPlugins();  
        QObject *create(const QString &mimeType,  
                const QUrl &url,  
                const QStringList &argumentNames,  
               const QStringList &argumentValues) const ;  
        bool extension(QWebPluginFactory::Extension extension, const QWebPluginFactory::ExtensionOption *option = 0
               QWebPluginFactory::ExtensionReturn *output = 0);  
        bool supportsExtension(QWebPluginFactory::Extension extension) const;  
    private:  
        // 用于将载入的插件记录下来  
        mutable QList<QList<QWebPluginFactory::Plugin> > pluginslist;  
        mutable QList<WebKitPluginInteface *> interfaces;  
}; 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

具体实现主要是create和plugins两个函数:

QList<QWebPluginFactory::Plugin> WebPluginFactory::plugins() const  
{  
    const char * s=getenv("BROWSER_PLUGIN_DIR");  
    static bool isFirst=true;  
    if(!isFirst)  
    {  
        return pluginslist;  
    }  
    isFirst=false;  
    QString spath;  
    if(s)  
    sspath=s;  
    else  
{  
spath=".";  
}  
    QDir dir(spath);  
    QStringList filters;  
    QString abspath=dir.absolutePath();  
filters<<"libqtweb*.so"; //查找下面的扩张,linux下是so,windows下则应该是dll,  
    QStringList files=dir.entryList(filters);  
    foreach(QString file,files)  
    {  
        file=dir.filePath(file);  
        QPluginLoader loader(file,0);  
        QObject * objloader.instance();  
//下面是载入自定义的接口,只有这样才能支持动态插件创建,如果固定死了,将不利于扩展,后一节会介绍这部分内容  
        WebKitPluginInteface * interfaceqobject_cast<WebKitPluginInteface*> (obj);  
        if(interface==0)  
       {  
            //ignore error when loading so ;  
            continue;  
        }  
        interface->plugins();  
        plugins.append(interface->plugins());  
        pluginslist.append(interface->plugins());  
        interfaces.append(interface);  
    }  
    return plugins;  
}  
void WebPluginFactory::refreshPlugins()  
{  
    Reload();  
}  
QObject * WebPluginFactory::create(const QString &mimeType,  
        const QUrl &url,  
        const QStringList &argumentNames,  
        const QStringList &argumentValues) const  
{  
    for(int i=0;i<pluginslist.size();i++)  
    {  
        for( int j=0;j< pluginslist[i].size();j++)  
        {  
            foreach(WebPluginFactory::MimeType mt, pluginslist[i][j].mimeTypes)  
            {  
                if(mt.name == mimeType) //查找到,创建实例  
                    return interfaces[i]->create( mimeType, url, argumentNames, argumentValues);  
            }  
        }  
    }  
    return NULL; //如果没有,直接返回NULL,webkit会进行处理的  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.

这两个最主要的接口都是围绕着mimetype进行的,通过返回的列表告诉webkit插件支持什么类型的文件,而create则根据mimetype来识别文件类型,然后创建相应的插件。

下一节会简单的创建一个插件来演示如何创建一个插件。

上一篇讲到可以通过扩展QWebPage接口进行动态载入插件,但是插件的接口并没有明确,这一篇通过介绍自定义的接口来实现插件的动态载入。

首先是接口的定义:

class WebKitPluginInteface  
{  
    public:  
        virtual ~WebKitPluginInteface(){};  
        virtual QList<QWebPluginFactory::Plugin> plugins()const =0;  
        virtual QObject *create(const QString &mimeType,  
                const QUrl &url,  
                const QStringList &argumentNames,  
                const QStringList &argumentValues) const =0;  
};  
 
Q_DECLARE_INTERFACE(WebKitPluginInteface, "baizx.cnblogs.com/1.0") 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

这样自定义的插件就可以通过实现这个接口来实现定制的插件。下面是一个例子:

class TestPlugin :public QObject,public WebKitPluginInteface  
{  
Q_OBJECT  
Q_INTERFACES(WebKitPluginInteface)  
    public:  
        TestPlugin(QObject * parent=0): WebkitPlugin(parent){};  
        virtual ~TestPlugin(){};  
        virtual QList<QWebPluginFactory::Plugin> plugins()const ;  
        virtual QObject *create(const QString &mimeType,  
                const QUrl &url,  
                const QStringList &argumentNames,  
                const QStringList &argumentValues) const ;  
};  
 
QList<QWebPluginFactory::Plugin> TestPlugin::plugins()const  
{  
    QList<QWebPluginFactory::Plugin> plugins ;  
    QWebPluginFactory::Plugin plugin;  
    QWebPluginFactory::MimeType mimeType;  
    QStringList strings;  
    plugin.name="testplugin";  
    plugin.description="testplugin !!!";  
    mimeType.name="application/x-textedit";  
    mimeType.description="test textedit";  
    strings.append(".etxt");  
    mimeType.fileExtensions=strings;  
    QList<QWebPluginFactory::MimeType> mimeTypes;  
    mimeTypes.append(mimeType);  
    plugin.mimeTypes=mimeTypes;  
    plugins.append(plugin);  
    return plugins;  
}  
 
QObject *TestPlugin::create(const QString &mimeType,  
                const QUrl &url,  
                const QStringList &argumentNames,  
                const QStringList &argumentValues) const  
{  
    QTextEdit * editnew QTextEdit();  
edit->setObjectName("我是插件");  
    edit->setPlainText(mimeType + url.toString() );  
    Q_UNUSED(argumentNames);  
    Q_UNUSED(argumentValues);  
    return edit;  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.

这样一个简单的插件就创建完毕了,具体实际应用中可能会用到很到参数,并且会载入实际的内容,这里只是一个演示。

小结:Qt Webkit浏览器插件设计实现的内容介绍完了,希望通过本文的学习能对你有所帮助!

责任编辑:zhaolei 来源: 互联网
相关推荐

2011-09-09 18:43:13

Qt Webkit浏览器

2011-08-29 14:27:33

QTWebkit浏览器

2010-07-21 15:06:33

2011-06-10 17:10:32

Qt GUI 浏览器

2011-09-01 14:04:45

QT Webkit插件

2013-03-06 11:10:12

WebKit浏览器

2011-08-08 09:25:55

2013-10-31 14:31:09

2009-11-11 13:00:05

GNOME浏览器Webkit内核

2011-09-09 17:39:58

WebKit浏览器

2010-04-28 10:39:43

Webkit浏览器内核

2011-06-10 16:44:17

Qt 浏览器

2013-11-22 09:58:36

2011-06-14 11:48:38

Webkit QT

2016-09-21 14:24:37

3D全景浏览器浏览器

2009-11-12 09:21:20

Chrome浏览器插件

2009-06-22 14:06:00

java浏览器

2013-02-18 10:39:53

OperaWebkit浏览器

2011-09-01 15:22:16

Qt WebKitWebKit

2010-01-21 09:02:51

搜狗浏览器Webkit
点赞
收藏

51CTO技术栈公众号