Windows平台WebKit的Plugin機制(一)——搜尋外掛程式

來源:互聯網
上載者:User

本文探討在Windows平台下,WebKit如何搜尋外掛程式。

用於測試的網頁代碼如下:

<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擷取完畢。我們的測試網頁,在我的電腦上顯示結果如下:

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.