Overview
在Safari里有一个单例对象WebPluginDatabase负责管理本地的插件,每个plugin对应一个WebBasePluginPackage,存放在plugins里。
在第一次调用sharedDatabase()会遍历当前系统有哪些可用的插件,并加到列表中管理。每个插件有其支持的MIME types和文件扩展名(Extension),在加载完成后,还会向WebView注册这些信息,以便在需要时加载对应的plugin。
当一个页面文档(WebDocumentView/WebHTMLView)决定要显示一个plugin时,与插件的交互管理主要集中在WebPluginController中。根据plugin的类型,执行初始化(webPluginInitialize)、释放(webPluginDestroy)、启动(webPluginStart)、停止(webPluginStop)等操作
(括号内的函数只是WebKit Plugin定义的函数)。
插件数据库的初始化
WebPluginDatabase是在需要时初始化,下面的序列图显示的是由视频页面创建视频时触发的WebPluginDatabase流程:
在WebFrameLoaderClient通过_videoProxyPluginForMIMEType获得一个WebPluginPackage,就会调用自身的pluginView函数创建一个插件对应的视图出来(在iOS里会创建一个UIWebPluginView封装起来)。再交由WebPluginController管理。
WebPluginPackage - 加载一个插件
如何从plugin中加载出一个视图?对应的就是下面这个流程。
1. 先在是初始化plugin database时就会使用获得的path让WebPluginPackage初始化一个NSBundle并存在成员变量中。
2. 在开始加载插件时,WebPluginController会操作WebPluginPackage执行[NSBundle load]并返回它的principalClass, 之后拿着这个class就可创建视图了(在iOS里会创建一个UIWebPluginView封装起来),再由WebPluginController管理(addPlugin
& addPlugInView)。
看一眼Plugin在info.plist定义了什么(QuickTime Plugin):
WebPluginController - 添加新的插件
下面的序列图包含三个主要过程(并非完整的call stack):
1. 在DocumentLoader发出finishedLoading()完成主文档加载时,会创建WebHTMLView, 在初始化时也会初始化一个WebPluginController对象。
2. 同样在finishedLoading()处理过程中,在为WebHTMLView指定WebDataSource的同时,也会为WebPluginController指定相同的data source.
3. 当一个有效的url被指定后(指定media element的src属性), 就开始了一系列的初始化行为。 WebPluginController仅是记录的作用。实际的视图管理是由RenderWidget和Widget来处理的。
*关于WebHTMLView看这里,关于WebDataSource看这里。
WebPluginController - 释放操作
下面说明两种时机下的释放时序图:
1. 当页面关闭时。由WebHTMLView的关闭操作发起释放操作。
2.当使用JS删除视频节点时。由JS Binding的JSNode发起操作。
WebPluginController - 与插件交互
根据WebKit Plugin Protocol的定义,一个WebKit插件主要提供以下实例接口函数:
因为已经获取plugin bundle里的视图的实例,就可以像一般的视图操作一样来与plugin交互了。WebPluginController使用下面的方式来调用这些函数:
if([aViewrespondsToSelector:@selector(webPlugInStart)])
{
JSC::JSLock::DropAllLocksdropAllLocks(JSDOMWindowBase::commonJSGlobalData());
[aViewwebPlugInStart];
}
转载请注明出处:http://blog.csdn.net/horkychen