一、认识Embedding接口
Gecko内核作为相对独立的部分嵌入到外部程序中,在本质上外部程序与Gecko内核的关系其实很类似Plugin与Gecko内核的关系,外部程序与Gecko内核需要分别实现一些接口,各负其责,以供对方调用,这样两者相互结合实现所要的功能。不过Gecko内核官方目前提供给外部调用的接口封装得不是很简单,使用起来也不是非常的方便,但通过对GTKMozEmbed、winEmbed等的了解,Gecko内核部分往往通过nsWebBrowser来实现public nsIWebBrowser、nsIWebNavigation、
nsIWebBrowserSetup、nsIDocShellTreeItem、nsIBaseWindow、nsIWebBrowserPersist、nsIWebBrowserFocus、 nsIWebProgressListener等接口,以代表一个浏览器页面浏览实例;
而外壳程序部分需要实现nsIWebBrowserChrome、nsIEmbeddingSiteWindow、nsIWebProgressListener、nsISHistoryListener、nsIContextMenuListener等接口以代表一个浏览器页面浏览外壳,供Gecko内核调用。
其中nsWebBrowser初始化后通过setcontainerWindow来设置其nsIWebBrowserChrome containerWindow为其对应的外壳实现,然后通过InitWindow、Create等方法可真正创建一个浏览器页面浏览实例,而外壳实现通过设置其nsIWebBrowser webBrowser为前面初始化的nsWebBrowser实例,这样两者可互为引用,同时外壳部分可向nsWebBrowser添加一些如WebProgress、ContextMenu等listener,以供Gecko内核nsWebBrowser需要时调用通知。
另外外壳部分需要实现接口nsIWindowCreator,并通过调用window watch service的方法setWindowCreator来告诉window watch service由外壳部分来createChromeWindow,以保证内核在由页面脚本通过window.open来打开新窗口时统一由外壳部分来创建新开的窗口。
上面提到的是Gecko内核为了实现Embedding,需要由内核部分与外壳部分分别实现的基本接口及相关调用关系,其中Gecko内核还提供有诸如NS_InitEmbedding、NS_TermEmbedding等XPCOM方面的接口以供外壳部分充分利用Gecko内核提供的XPCOM强大组件管理等功能。
为了更方便外壳程序的调用,Gecko也提供了诸如GtkMozEmbed widget及MozApp、MozView、 MozViewListener等,其实质仍属于上面提到的外壳部分,只不过更加的方便用户使用罢了。
二、外部程序如何嵌入Gecko内核
为了能真正了解如何将目前的Gecko内核嵌入到外部程序中,最好还是先参考Roll your own browser - An embedding HowTo按照其提供的编译方式,了解TestGtkEmbed、mfcEmbed等实现。通过对这些实例的了解才能对嵌入Gecko内核有一定的了解。
外部程序嵌入Gecko内核的主要步骤如下:
1、通过NS_InitEmbedding初始化内核;
2、通过 do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv)创建mWebBrowser;
3、创建实现nsIWebBrowserChrome、nsIEmbeddingSiteWindow接口实例mpBrowserImpl;
4、创建绑定窗口
mpBrowserImpl->Init(mpBrowserFrameGlue, mWebBrowser);
mWebBrowser->SetContainerWindow(NS_STATIC_CAST(nsIWebBrowserChrome*, mpBrowserImpl));
nsCOMPtr
if (setup)
setup->SetProperty(nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER,PR_TRUE);
rv = mBaseWindow->InitWindow(nsNativeWidget(m_hWnd), nsnull,0, 0, rcLocation.right - rcLocation.left, rcLocation.bottom - rcLocation.top);
rv = mBaseWindow->Create();
5、添加监听
void mWebBrowser->AddWebBrowserListener(weakling, NS_GET_IID(nsIWebProgressListener));
6、设定WindowCreator、preference及promptservice等;
7、装载页面mWebNav=nsCOMPtr
if(mWebNav)
mWebNav->loadURI();
8、通过NS_TermEmbedding卸载内核,退出程序;
三、
同样作为浏览器内核,其实有很多文章就Gecko内核、IE内核、Webkit等多方面进行过比较如Comparison of layout engines。但就嵌入易用方面来讲,它们之间差别还是蛮大的,个人认为IE内核充分利用windows com技术,作为一个独立的ActiveX,其拥有很好接口封装,对windows用户来讲,大大提高了其易用性复用性;
Webkit内核本身一开始就专注于浏览器内核部分如KHTML、KJS,其提供给windows、gtk、mac等方面的接口也相对完毕;
Gecko内核往往不仅仅专注于浏览器内核如HTML、Javascript等方面,同时它还提供了XPCOM、XUL,从大的方面看,嵌入Gecko内核访问通用的html类的Web网站,只利用了其中一部分功能,其XUL、XPCOM等功能几乎可以不用,这样一来也是一种浪费,所以目前Embedding方面的接口,既要考虑到XPCOM方面,又要考虑到用户嵌入内核的易用性,显然没有IE内核及Webkit内核,简单明了,要想嵌入Gecko内核,需要对其进行深入的了解,这样反而降低了嵌入的意义。
顺便提一下,Avant/Orca Browser创始人宣称花了3年多的时间才将Gecko内核研究透彻,弄出个基于Gecko内核的浏览器Orca Browser,但其利用方式,不是基于Embedding的,而是基于Xulrunner的,这样既迎合了Gecko本身,同时能充分利用其强大功能,可谓一举两得,但是要想用好它,可要花上3、5年功夫不可。
四、总结
其实目前通过Embedding的方式使用Gecko内核的还不是很多,使用起来也比较困难,需要较深入的了解XPCOM等内核知识,比较好的实例也就只有上面提到的TestGtkEmbed、mfcEmbed等,可喜的是Mozilla最近似乎想重新加强其对Embedding方面的支持。详见Embedding/NewApi 及Chris Blizzard's blog。
另外Second life提供了一组接口以更加方便嵌入Gecko内核。详见uBrowser and LLMozLib。
四、参考资源
Mozilla project Embedding Mozilla
Mozilla developer center-Embedding Mozilla
Mozilla Embedding FAQ
Gecko Embedding Basics
Mozilla embedding APIs overview
1 条评论:
Mozilla Embedding API - New Status from Mark Finkle's Weblog
发表评论