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

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

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

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

 
  
  1. QObject * QWebPage::createPlugin (   
  2. const QString   
  3. & classid, const QUrl   
  4. & url, const QStringList   
  5. & paramNames, const QStringList ¶mValues   

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

下面是一个例子:

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

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

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

并且还可以在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这个纯虚基类。先看看他的声明:

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

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

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

因此重新实现的WebPluginFactory如下:

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

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

 
  
  1. QList<QWebPluginFactory::Plugin> WebPluginFactory::plugins() const  
  2. {  
  3.     const char * s=getenv("BROWSER_PLUGIN_DIR");  
  4.     static bool isFirst=true;  
  5.     if(!isFirst)  
  6.     {  
  7.         return pluginslist;  
  8.     }  
  9.     isFirst=false;  
  10.     QString spath;  
  11.     if(s)  
  12.     sspath=s;  
  13.     else  
  14. {  
  15. spath=".";  
  16. }  
  17.     QDir dir(spath);  
  18.     QStringList filters;  
  19.     QString abspath=dir.absolutePath();  
  20. filters<<"libqtweb*.so"; //查找下面的扩张,linux下是so,windows下则应该是dll,  
  21.     QStringList files=dir.entryList(filters);  
  22.     foreach(QString file,files)  
  23.     {  
  24.         file=dir.filePath(file);  
  25.         QPluginLoader loader(file,0);  
  26.         QObject * objloader.instance();  
  27. //下面是载入自定义的接口,只有这样才能支持动态插件创建,如果固定死了,将不利于扩展,后一节会介绍这部分内容  
  28.         WebKitPluginInteface * interfaceqobject_cast<WebKitPluginInteface*> (obj);  
  29.         if(interface==0)  
  30.        {  
  31.             //ignore error when loading so ;  
  32.             continue;  
  33.         }  
  34.         interface->plugins();  
  35.         plugins.append(interface->plugins());  
  36.         pluginslist.append(interface->plugins());  
  37.         interfaces.append(interface);  
  38.     }  
  39.     return plugins;  
  40. }  
  41. void WebPluginFactory::refreshPlugins()  
  42. {  
  43.     Reload();  
  44. }  
  45. QObject * WebPluginFactory::create(const QString &mimeType,  
  46.         const QUrl &url,  
  47.         const QStringList &argumentNames,  
  48.         const QStringList &argumentValues) const  
  49. {  
  50.     for(int i=0;i<pluginslist.size();i++)  
  51.     {  
  52.         for( int j=0;j< pluginslist[i].size();j++)  
  53.         {  
  54.             foreach(WebPluginFactory::MimeType mt, pluginslist[i][j].mimeTypes)  
  55.             {  
  56.                 if(mt.name == mimeType) //查找到,创建实例  
  57.                     return interfaces[i]->create( mimeType, url, argumentNames, argumentValues);  
  58.             }  
  59.         }  
  60.     }  
  61.     return NULL; //如果没有,直接返回NULL,webkit会进行处理的  

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

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

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

首先是接口的定义:

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

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

 
  
  1. class TestPlugin :public QObject,public WebKitPluginInteface  
  2. {  
  3. Q_OBJECT  
  4. Q_INTERFACES(WebKitPluginInteface)  
  5.     public:  
  6.         TestPlugin(QObject * parent=0): WebkitPlugin(parent){};  
  7.         virtual ~TestPlugin(){};  
  8.         virtual QList<QWebPluginFactory::Plugin> plugins()const ;  
  9.         virtual QObject *create(const QString &mimeType,  
  10.                 const QUrl &url,  
  11.                 const QStringList &argumentNames,  
  12.                 const QStringList &argumentValues) const ;  
  13. };  
  14.  
  15. QList<QWebPluginFactory::Plugin> TestPlugin::plugins()const  
  16. {  
  17.     QList<QWebPluginFactory::Plugin> plugins ;  
  18.     QWebPluginFactory::Plugin plugin;  
  19.     QWebPluginFactory::MimeType mimeType;  
  20.     QStringList strings;  
  21.     plugin.name="testplugin";  
  22.     plugin.description="testplugin !!!";  
  23.     mimeType.name="application/x-textedit";  
  24.     mimeType.description="test textedit";  
  25.     strings.append(".etxt");  
  26.     mimeType.fileExtensions=strings;  
  27.     QList<QWebPluginFactory::MimeType> mimeTypes;  
  28.     mimeTypes.append(mimeType);  
  29.     plugin.mimeTypes=mimeTypes;  
  30.     plugins.append(plugin);  
  31.     return plugins;  
  32. }  
  33.  
  34. QObject *TestPlugin::create(const QString &mimeType,  
  35.                 const QUrl &url,  
  36.                 const QStringList &argumentNames,  
  37.                 const QStringList &argumentValues) const  
  38. {  
  39.     QTextEdit * editnew QTextEdit();  
  40. edit->setObjectName("我是插件");  
  41.     edit->setPlainText(mimeType + url.toString() );  
  42.     Q_UNUSED(argumentNames);  
  43.     Q_UNUSED(argumentValues);  
  44.     return edit;  

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

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

 

你可能感兴趣的:(qt-webkit学习)