Windows平台WebKit的Plugin机制(一)——搜索插件
2011-08-14 13:53
267 查看
本文探讨在Windows平台下,WebKit如何搜索插件。
用于测试的网页代码如下:
这个网页的作用是列出当前浏览器支持的插件名称、描述和对应的文件。
WebKit的插件是延迟加载,并非一打开浏览器就加载所有插件。这个例子中,当JS执行到navigator.plugins.length时,才开始初始化插件信息,此刻的调用栈截图如下:
PluginDatabase对象构造完后,将会到几个特定的目录下寻找插件,这部分代码片段如下:
其中:
sarariPluginsDirectory()返回的是WebKit当前目录(exe文件所在的目录)下的Plugins子目录;
addQuickTimePluginDirectory()到注册表HKEY_LOCAL_MACHINE\Software\AppleComputer, Inc.\QuickTime下寻找InstallDir键,取它的值;
addAdobeAcrobatPluginDirectory()到注册表HKEY_LOCAL_MACHINE\Software\Adobe\AcrobatReader下寻找InstallPath键,取它的值(同时也会记录Adobe的版本号);
addMozillaPluginDirectories()到注册表HKEY_LOCAL_MACHINE\Software\Mozilla,遍历其子目录,寻找Plugins键,取它的值;
addWindowsMediaPlayerPluginDirectory()首先加入“C:\PFiles\Plugins”这个路径,再加入注册表HKEY_LOCAL_MACHINE\Software\Microsoft\MediaPlayer下Installation Directory的值;
addMacromediaPluginDirectories()加入了“C:\Windows\system32\macromed\Flash”和“C:\Windows\system32\macromed\Shockwave10”目录。
接下来,WebKit会遍历加入的这些目录,寻找np打头的dll文件,或者,如果遍历的目录是以“Shockwave 10”结尾,则寻找Plugin.dll,记录其路径。做完这些之后,WebKit还会到注册表HKEY_LOCAL_MACHINE\Software\MozillaPlugins和HKEY_CURRENT_USER\Software\MozillaPlugins下,遍历子目录,寻找Path键,将值记录下来。
经过以上步骤,WebKit会得到Windows下可用作插件的dll文件路径的集合。WebKit还会记录这些文件的最后修改时间,将来如果要重新加载插件,而dll文件最后修改时间有更新,则可能要重新获取dll文件的信息和加载新的dll文件。
WebKit获取dll文件信息的逻辑实现在PluginPackageWin.cpp的PluginPackage::fetchInfo()里,代码如下:
这个方法使用Wndows API,获取dll文件的ProductName、FileDescription、Version、MIMEType、FileExtents、FileOpenName等信息(GetFileVersionInfoW(const_cast<UChar*>(m_path.charactersWithNullTermination()), 0, versionInfoSize, versionInfoData.get()),其中m_path存储了dll文件的路径)。我们测试网页中列出的插件名称和描述,就是在这个方法中获得的。这个方法还调用了另一个有意思的方法PluginPackage::isPluginBlacklisted()来判断插件是否被禁止。具体哪些插件被禁止以及为什么被禁止,想了解的人可以去看看这个方法。
通过以上步骤,PluginInfo获取完毕。我们的测试网页,在我的电脑上显示结果如下:
用于测试的网页代码如下:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> </head> <body> <script language=javascript> var len = navigator.plugins.length; document.write("你的浏览器共支持" + len + "种plug-in:<BR>"); document.write("<TABLE BORDER>"); document.write("<CAPTION>PLUG-IN 清单</CAPTION>"); document.write("<TR><TH>编号</TH><TH>名称</TH><TH>描述</TH><TH>文件名</TH></TR>"); for (var i=0; i<len; i++){ document.write("<TR><TD>" + i + "</TD>" + "<TD>" + navigator.plugins[i].name + "</TD>" + "<TD>" + navigator.plugins[i].description + "</TD>" + "<TD>" + navigator.plugins[i].filename) + "</TD></TR>"; } document.write("</TABLE>"); </script> </body> </html>
这个网页的作用是列出当前浏览器支持的插件名称、描述和对应的文件。
WebKit的插件是延迟加载,并非一打开浏览器就加载所有插件。这个例子中,当JS执行到navigator.plugins.length时,才开始初始化插件信息,此刻的调用栈截图如下:
PluginDatabase对象构造完后,将会到几个特定的目录下寻找插件,这部分代码片段如下:
Vector<String> PluginDatabase::defaultPluginDirectories() { Vector<String> directories; String ourDirectory = safariPluginsDirectory(); if (!ourDirectory.isNull()) directories.append(ourDirectory); addQuickTimePluginDirectory(directories); addAdobeAcrobatPluginDirectory(directories); addMozillaPluginDirectories(directories); addWindowsMediaPlayerPluginDirectory(directories); addMacromediaPluginDirectories(directories); #if PLATFORM(QT) addJavaPluginDirectory(directories); #endif return directories; }
其中:
sarariPluginsDirectory()返回的是WebKit当前目录(exe文件所在的目录)下的Plugins子目录;
addQuickTimePluginDirectory()到注册表HKEY_LOCAL_MACHINE\Software\AppleComputer, Inc.\QuickTime下寻找InstallDir键,取它的值;
addAdobeAcrobatPluginDirectory()到注册表HKEY_LOCAL_MACHINE\Software\Adobe\AcrobatReader下寻找InstallPath键,取它的值(同时也会记录Adobe的版本号);
addMozillaPluginDirectories()到注册表HKEY_LOCAL_MACHINE\Software\Mozilla,遍历其子目录,寻找Plugins键,取它的值;
addWindowsMediaPlayerPluginDirectory()首先加入“C:\PFiles\Plugins”这个路径,再加入注册表HKEY_LOCAL_MACHINE\Software\Microsoft\MediaPlayer下Installation Directory的值;
addMacromediaPluginDirectories()加入了“C:\Windows\system32\macromed\Flash”和“C:\Windows\system32\macromed\Shockwave10”目录。
接下来,WebKit会遍历加入的这些目录,寻找np打头的dll文件,或者,如果遍历的目录是以“Shockwave 10”结尾,则寻找Plugin.dll,记录其路径。做完这些之后,WebKit还会到注册表HKEY_LOCAL_MACHINE\Software\MozillaPlugins和HKEY_CURRENT_USER\Software\MozillaPlugins下,遍历子目录,寻找Path键,将值记录下来。
经过以上步骤,WebKit会得到Windows下可用作插件的dll文件路径的集合。WebKit还会记录这些文件的最后修改时间,将来如果要重新加载插件,而dll文件最后修改时间有更新,则可能要重新获取dll文件的信息和加载新的dll文件。
WebKit获取dll文件信息的逻辑实现在PluginPackageWin.cpp的PluginPackage::fetchInfo()里,代码如下:
bool PluginPackage::fetchInfo() { DWORD versionInfoSize, zeroHandle; versionInfoSize = GetFileVersionInfoSizeW(const_cast<UChar*>(m_path.charactersWithNullTermination()), &zeroHandle); if (versionInfoSize == 0) return false; OwnArrayPtr<char> versionInfoData = adoptArrayPtr(new char[versionInfoSize]); if (!GetFileVersionInfoW(const_cast<UChar*>(m_path.charactersWithNullTermination()), 0, versionInfoSize, versionInfoData.get())) return false; m_name = getVersionInfo(versionInfoData.get(), "ProductName"); m_description = getVersionInfo(versionInfoData.get(), "FileDescription"); if (m_name.isNull() || m_description.isNull()) return false; VS_FIXEDFILEINFO* info; UINT infoSize; if (!VerQueryValueW(versionInfoData.get(), L"\\", (LPVOID*) &info, &infoSize) || infoSize < sizeof(VS_FIXEDFILEINFO)) return false; m_moduleVersion.leastSig = info->dwFileVersionLS; m_moduleVersion.mostSig = info->dwFileVersionMS; if (isPluginBlacklisted()) return false; Vector<String> types; getVersionInfo(versionInfoData.get(), "MIMEType").split('|', types); Vector<String> extensionLists; getVersionInfo(versionInfoData.get(), "FileExtents").split('|', extensionLists); Vector<String> descriptions; getVersionInfo(versionInfoData.get(), "FileOpenName").split('|', descriptions); for (unsigned i = 0; i < types.size(); i++) { String type = types[i].lower(); String description = i < descriptions.size() ? descriptions[i] : ""; String extensionList = i < extensionLists.size() ? extensionLists[i] : ""; Vector<String> extensionsVector; extensionList.split(',', extensionsVector); // Get rid of the extension list that may be at the end of the description string. int pos = description.find("(*"); if (pos != -1) { // There might be a space that we need to get rid of. if (pos > 1 && description[pos - 1] == ' ') pos--; description = description.left(pos); } // Determine the quirks for the MIME types this plug-in supports determineQuirks(type); m_mimeToExtensions.add(type, extensionsVector); m_mimeToDescriptions.add(type, description); } return true; }
这个方法使用Wndows API,获取dll文件的ProductName、FileDescription、Version、MIMEType、FileExtents、FileOpenName等信息(GetFileVersionInfoW(const_cast<UChar*>(m_path.charactersWithNullTermination()), 0, versionInfoSize, versionInfoData.get()),其中m_path存储了dll文件的路径)。我们测试网页中列出的插件名称和描述,就是在这个方法中获得的。这个方法还调用了另一个有意思的方法PluginPackage::isPluginBlacklisted()来判断插件是否被禁止。具体哪些插件被禁止以及为什么被禁止,想了解的人可以去看看这个方法。
通过以上步骤,PluginInfo获取完毕。我们的测试网页,在我的电脑上显示结果如下:
相关文章推荐
- 编译hadoop1.04 eclipse plugin插件 详解 在windows linux平台均可
- Android系统实现DroidPlugin插件机制
- Windows下使用Hadoop-eclipse-plugin插件
- Windows平台下安装Eclipse插件,开发Hadoop应用
- Windows 平台下Myeclipse 10 中SVN 插件使用教程(TortoiseSVN)
- Windows平台下安装Eclipse插件,开发Hadoop应用
- NPAPI插件开发学习:Webkit的插件机制
- 在Windows平台上使用Git和pathogen管理gVim插件
- Windows平台下安装Eclipse插件,开发Hadoop应用
- Windows下使用Ant编译hadoop-eclipse-plugin-2.x插件
- Windows平台编译Webkit
- Windows下动态链接之一:DLL插件机制的装载和使用
- golang的 IntelliJ Idea插件 google-go-lang-idea-plugin 编译方法 build in windows
- NPAPI插件开发学习:Webkit的插件机制
- Windows 平台下Myeclipse 10 中SVN 插件使用教程(TortoiseSVN)
- Chromium插件(Plugin)机制简要介绍和学习计划
- windows编译hadoop 2.x Hadoop-eclipse-plugin插件
- WebKit 在 Windows 平台下编译小结
- Windows平台几种同步机制的性能实证
- Hadoop II Windows下安装hadoop2.6.0-eclipse-plugin插件