WebCore/plugins/win/PluginDatabaseWin.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
       
     3  * Copyright (C) 2008 Collabora, Ltd.  All rights reserved.
       
     4  * Copyright (C) 2008-2009 Torch Mobile, Inc.  All rights reserved.
       
     5  *
       
     6  * Redistribution and use in source and binary forms, with or without
       
     7  * modification, are permitted provided that the following conditions
       
     8  * are met:
       
     9  * 1. Redistributions of source code must retain the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer.
       
    11  * 2. Redistributions in binary form must reproduce the above copyright
       
    12  *    notice, this list of conditions and the following disclaimer in the
       
    13  *    documentation and/or other materials provided with the distribution.
       
    14  *
       
    15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
       
    16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
       
    19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
       
    26  */
       
    27 
       
    28 #include "config.h"
       
    29 #include "PluginDatabase.h"
       
    30 
       
    31 #include "Frame.h"
       
    32 #include "KURL.h"
       
    33 #include "PluginPackage.h"
       
    34 #include <windows.h>
       
    35 #include <shlwapi.h>
       
    36 
       
    37 #if COMPILER(MINGW)
       
    38 #define _countof(x) (sizeof(x)/sizeof(x[0]))
       
    39 #endif
       
    40 
       
    41 #if OS(WINCE)
       
    42 // WINCE doesn't support Registry Key Access Rights. The parameter should always be 0
       
    43 #define KEY_ENUMERATE_SUB_KEYS 0
       
    44 
       
    45 DWORD SHGetValue(HKEY hkey, LPCWSTR pszSubKey, LPCWSTR pszValue, LPDWORD pdwType, LPVOID pvData, LPDWORD pcbData)
       
    46 {
       
    47     HKEY key;
       
    48     if (RegOpenKeyEx(hkey, pszSubKey, 0, 0, &key) == ERROR_SUCCESS) {
       
    49         DWORD result = RegQueryValueEx(key, pszValue, 0, pdwType, (LPBYTE)pvData, pcbData);
       
    50         RegCloseKey(key);
       
    51         return result;
       
    52     }
       
    53     return ERROR_INVALID_NAME;
       
    54 }
       
    55 
       
    56 BOOL PathRemoveFileSpec(LPWSTR moduleFileNameStr)
       
    57 {
       
    58     if (!*moduleFileNameStr)
       
    59         return FALSE;
       
    60 
       
    61     LPWSTR lastPos = 0;
       
    62     LPWSTR curPos = moduleFileNameStr;
       
    63     do {
       
    64         if (*curPos == L'/' || *curPos == L'\\')
       
    65             lastPos = curPos;
       
    66     } while (*++curPos);
       
    67 
       
    68     if (lastPos == curPos - 1)
       
    69         return FALSE;
       
    70 
       
    71     if (lastPos)
       
    72         *lastPos = 0;
       
    73     else {
       
    74         moduleFileNameStr[0] = L'\\';
       
    75         moduleFileNameStr[1] = 0;
       
    76     }
       
    77 
       
    78     return TRUE;
       
    79 }
       
    80 #endif
       
    81 
       
    82 namespace WebCore {
       
    83 
       
    84 static inline void addPluginPathsFromRegistry(HKEY rootKey, HashSet<String>& paths)
       
    85 {
       
    86     HKEY key;
       
    87     HRESULT result = RegOpenKeyExW(rootKey, L"Software\\MozillaPlugins", 0, KEY_ENUMERATE_SUB_KEYS, &key);
       
    88 
       
    89     if (result != ERROR_SUCCESS)
       
    90         return;
       
    91 
       
    92     wchar_t name[128];
       
    93     FILETIME lastModified;
       
    94 
       
    95     // Enumerate subkeys
       
    96     for (int i = 0;; i++) {
       
    97         DWORD nameLen = _countof(name);
       
    98         result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
       
    99 
       
   100         if (result != ERROR_SUCCESS)
       
   101             break;
       
   102 
       
   103         WCHAR pathStr[_MAX_PATH];
       
   104         DWORD pathStrSize = sizeof(pathStr);
       
   105         DWORD type;
       
   106 
       
   107         result = SHGetValue(key, name, TEXT("Path"), &type, (LPBYTE)pathStr, &pathStrSize);
       
   108         if (result != ERROR_SUCCESS || type != REG_SZ)
       
   109             continue;
       
   110 
       
   111         paths.add(String(pathStr, pathStrSize / sizeof(WCHAR) - 1));
       
   112     }
       
   113 
       
   114     RegCloseKey(key);
       
   115 }
       
   116 
       
   117 void PluginDatabase::getPluginPathsInDirectories(HashSet<String>& paths) const
       
   118 {
       
   119     // FIXME: This should be a case insensitive set.
       
   120     HashSet<String> uniqueFilenames;
       
   121 
       
   122     HANDLE hFind = INVALID_HANDLE_VALUE;
       
   123     WIN32_FIND_DATAW findFileData;
       
   124 
       
   125     String oldWMPPluginPath;
       
   126     String newWMPPluginPath;
       
   127 
       
   128     Vector<String>::const_iterator end = m_pluginDirectories.end();
       
   129     for (Vector<String>::const_iterator it = m_pluginDirectories.begin(); it != end; ++it) {
       
   130         String pattern = *it + "\\*";
       
   131 
       
   132         hFind = FindFirstFileW(pattern.charactersWithNullTermination(), &findFileData);
       
   133 
       
   134         if (hFind == INVALID_HANDLE_VALUE)
       
   135             continue;
       
   136 
       
   137         do {
       
   138             if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
       
   139                 continue;
       
   140 
       
   141             String filename = String(findFileData.cFileName, wcslen(findFileData.cFileName));
       
   142             if ((!filename.startsWith("np", false) || !filename.endsWith("dll", false)) &&
       
   143                 (!equalIgnoringCase(filename, "Plugin.dll") || !it->endsWith("Shockwave 10", false)))
       
   144                 continue;
       
   145 
       
   146             String fullPath = *it + "\\" + filename;
       
   147             if (!uniqueFilenames.add(fullPath).second)
       
   148                 continue;
       
   149 
       
   150             paths.add(fullPath);
       
   151 
       
   152             if (equalIgnoringCase(filename, "npdsplay.dll"))
       
   153                 oldWMPPluginPath = fullPath;
       
   154             else if (equalIgnoringCase(filename, "np-mswmp.dll"))
       
   155                 newWMPPluginPath = fullPath;
       
   156 
       
   157         } while (FindNextFileW(hFind, &findFileData) != 0);
       
   158 
       
   159         FindClose(hFind);
       
   160     }
       
   161 
       
   162     addPluginPathsFromRegistry(HKEY_LOCAL_MACHINE, paths);
       
   163     addPluginPathsFromRegistry(HKEY_CURRENT_USER, paths);
       
   164 
       
   165     // If both the old and new WMP plugin are present in the plugins set, 
       
   166     // we remove the old one so we don't end up choosing the old one.
       
   167     if (!oldWMPPluginPath.isEmpty() && !newWMPPluginPath.isEmpty())
       
   168         paths.remove(oldWMPPluginPath);
       
   169 }
       
   170 
       
   171 static inline Vector<int> parseVersionString(const String& versionString)
       
   172 {
       
   173     Vector<int> version;
       
   174 
       
   175     unsigned startPos = 0;
       
   176     unsigned endPos;
       
   177     
       
   178     while (startPos < versionString.length()) {
       
   179         for (endPos = startPos; endPos < versionString.length(); ++endPos)
       
   180             if (versionString[endPos] == '.' || versionString[endPos] == '_')
       
   181                 break;
       
   182 
       
   183         int versionComponent = versionString.substring(startPos, endPos - startPos).toInt();
       
   184         version.append(versionComponent);
       
   185 
       
   186         startPos = endPos + 1;
       
   187     }
       
   188 
       
   189     return version;
       
   190 }
       
   191 
       
   192 // This returns whether versionA is higher than versionB
       
   193 static inline bool compareVersions(const Vector<int>& versionA, const Vector<int>& versionB)
       
   194 {
       
   195     for (unsigned i = 0; i < versionA.size(); i++) {
       
   196         if (i >= versionB.size())
       
   197             return true;
       
   198 
       
   199         if (versionA[i] > versionB[i])
       
   200             return true;
       
   201         else if (versionA[i] < versionB[i])
       
   202             return false;
       
   203     }
       
   204 
       
   205     // If we come here, the versions are either the same or versionB has an extra component, just return false
       
   206     return false;
       
   207 }
       
   208 
       
   209 static inline void addMozillaPluginDirectories(Vector<String>& directories)
       
   210 {
       
   211     // Enumerate all Mozilla plugin directories in the registry
       
   212     HKEY key;
       
   213     LONG result;
       
   214     
       
   215     result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Mozilla"), 0, KEY_READ, &key);
       
   216     if (result == ERROR_SUCCESS) {
       
   217         WCHAR name[128];
       
   218         FILETIME lastModified;
       
   219 
       
   220         // Enumerate subkeys
       
   221         for (int i = 0;; i++) {
       
   222             DWORD nameLen = sizeof(name) / sizeof(WCHAR);
       
   223             result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
       
   224 
       
   225             if (result != ERROR_SUCCESS)
       
   226                 break;
       
   227 
       
   228             String extensionsPath = String(name, nameLen) + "\\Extensions";
       
   229             HKEY extensionsKey;
       
   230 
       
   231             // Try opening the key
       
   232             result = RegOpenKeyEx(key, extensionsPath.charactersWithNullTermination(), 0, KEY_READ, &extensionsKey);
       
   233 
       
   234             if (result == ERROR_SUCCESS) {
       
   235                 // Now get the plugins directory
       
   236                 WCHAR pluginsDirectoryStr[_MAX_PATH];
       
   237                 DWORD pluginsDirectorySize = sizeof(pluginsDirectoryStr);
       
   238                 DWORD type;
       
   239 
       
   240                 result = RegQueryValueEx(extensionsKey, TEXT("Plugins"), 0, &type, (LPBYTE)&pluginsDirectoryStr, &pluginsDirectorySize);
       
   241 
       
   242                 if (result == ERROR_SUCCESS && type == REG_SZ)
       
   243                     directories.append(String(pluginsDirectoryStr, pluginsDirectorySize / sizeof(WCHAR) - 1));
       
   244 
       
   245                 RegCloseKey(extensionsKey);
       
   246             }
       
   247         }
       
   248         
       
   249         RegCloseKey(key);
       
   250     }
       
   251 }
       
   252 
       
   253 static inline void addWindowsMediaPlayerPluginDirectory(Vector<String>& directories)
       
   254 {
       
   255 #if !OS(WINCE)
       
   256     // The new WMP Firefox plugin is installed in \PFiles\Plugins if it can't find any Firefox installs
       
   257     WCHAR pluginDirectoryStr[_MAX_PATH + 1];
       
   258     DWORD pluginDirectorySize = ::ExpandEnvironmentStringsW(TEXT("%SYSTEMDRIVE%\\PFiles\\Plugins"), pluginDirectoryStr, _countof(pluginDirectoryStr));
       
   259 
       
   260     if (pluginDirectorySize > 0 && pluginDirectorySize <= _countof(pluginDirectoryStr))
       
   261         directories.append(String(pluginDirectoryStr, pluginDirectorySize - 1));
       
   262 #endif
       
   263 
       
   264     DWORD type;
       
   265     WCHAR installationDirectoryStr[_MAX_PATH];
       
   266     DWORD installationDirectorySize = sizeof(installationDirectoryStr);
       
   267 
       
   268     HRESULT result = SHGetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\MediaPlayer"), TEXT("Installation Directory"), &type, (LPBYTE)&installationDirectoryStr, &installationDirectorySize);
       
   269 
       
   270     if (result == ERROR_SUCCESS && type == REG_SZ)
       
   271         directories.append(String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1));
       
   272 }
       
   273 
       
   274 static inline void addQuickTimePluginDirectory(Vector<String>& directories)
       
   275 {
       
   276     DWORD type;
       
   277     WCHAR installationDirectoryStr[_MAX_PATH];
       
   278     DWORD installationDirectorySize = sizeof(installationDirectoryStr);
       
   279 
       
   280     HRESULT result = SHGetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Apple Computer, Inc.\\QuickTime"), TEXT("InstallDir"), &type, (LPBYTE)&installationDirectoryStr, &installationDirectorySize);
       
   281 
       
   282     if (result == ERROR_SUCCESS && type == REG_SZ) {
       
   283         String pluginDir = String(installationDirectoryStr, installationDirectorySize / sizeof(WCHAR) - 1) + "\\plugins";
       
   284         directories.append(pluginDir);
       
   285     }
       
   286 }
       
   287 
       
   288 static inline void addAdobeAcrobatPluginDirectory(Vector<String>& directories)
       
   289 {
       
   290     HKEY key;
       
   291     HRESULT result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Adobe\\Acrobat Reader"), 0, KEY_READ, &key);
       
   292     if (result != ERROR_SUCCESS)
       
   293         return;
       
   294 
       
   295     WCHAR name[128];
       
   296     FILETIME lastModified;
       
   297 
       
   298     Vector<int> latestAcrobatVersion;
       
   299     String latestAcrobatVersionString;
       
   300 
       
   301     // Enumerate subkeys
       
   302     for (int i = 0;; i++) {
       
   303         DWORD nameLen = sizeof(name) / sizeof(WCHAR);
       
   304         result = RegEnumKeyExW(key, i, name, &nameLen, 0, 0, 0, &lastModified);
       
   305 
       
   306         if (result != ERROR_SUCCESS)
       
   307             break;
       
   308 
       
   309         Vector<int> acrobatVersion = parseVersionString(String(name, nameLen));
       
   310         if (compareVersions(acrobatVersion, latestAcrobatVersion)) {
       
   311             latestAcrobatVersion = acrobatVersion;
       
   312             latestAcrobatVersionString = String(name, nameLen);
       
   313         }
       
   314     }
       
   315 
       
   316     if (!latestAcrobatVersionString.isNull()) {
       
   317         DWORD type;
       
   318         WCHAR acrobatInstallPathStr[_MAX_PATH];
       
   319         DWORD acrobatInstallPathSize = sizeof(acrobatInstallPathStr);
       
   320 
       
   321         String acrobatPluginKeyPath = "Software\\Adobe\\Acrobat Reader\\" + latestAcrobatVersionString + "\\InstallPath";
       
   322         result = SHGetValue(HKEY_LOCAL_MACHINE, acrobatPluginKeyPath.charactersWithNullTermination(), 0, &type, (LPBYTE)acrobatInstallPathStr, &acrobatInstallPathSize);
       
   323 
       
   324         if (result == ERROR_SUCCESS) {
       
   325             String acrobatPluginDirectory = String(acrobatInstallPathStr, acrobatInstallPathSize / sizeof(WCHAR) - 1) + "\\browser";
       
   326             directories.append(acrobatPluginDirectory);
       
   327         }
       
   328     }
       
   329 
       
   330     RegCloseKey(key);
       
   331 }
       
   332 
       
   333 static inline String safariPluginsDirectory()
       
   334 {
       
   335     WCHAR moduleFileNameStr[_MAX_PATH];
       
   336     static String pluginsDirectory;
       
   337     static bool cachedPluginDirectory = false;
       
   338 
       
   339     if (!cachedPluginDirectory) {
       
   340         cachedPluginDirectory = true;
       
   341 
       
   342         int moduleFileNameLen = GetModuleFileName(0, moduleFileNameStr, _MAX_PATH);
       
   343 
       
   344         if (!moduleFileNameLen || moduleFileNameLen == _MAX_PATH)
       
   345             goto exit;
       
   346 
       
   347         if (!PathRemoveFileSpec(moduleFileNameStr))
       
   348             goto exit;
       
   349 
       
   350         pluginsDirectory = String(moduleFileNameStr) + "\\Plugins";
       
   351     }
       
   352 exit:
       
   353     return pluginsDirectory;
       
   354 }
       
   355 
       
   356 static inline void addMacromediaPluginDirectories(Vector<String>& directories)
       
   357 {
       
   358 #if !OS(WINCE)
       
   359     WCHAR systemDirectoryStr[MAX_PATH];
       
   360 
       
   361     if (GetSystemDirectory(systemDirectoryStr, _countof(systemDirectoryStr)) == 0)
       
   362         return;
       
   363 
       
   364     WCHAR macromediaDirectoryStr[MAX_PATH];
       
   365 
       
   366     PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Flash"));
       
   367     directories.append(macromediaDirectoryStr);
       
   368 
       
   369     PathCombine(macromediaDirectoryStr, systemDirectoryStr, TEXT("macromed\\Shockwave 10"));
       
   370     directories.append(macromediaDirectoryStr);
       
   371 #endif
       
   372 }
       
   373 
       
   374 Vector<String> PluginDatabase::defaultPluginDirectories()
       
   375 {
       
   376     Vector<String> directories;
       
   377     String ourDirectory = safariPluginsDirectory();
       
   378 
       
   379     if (!ourDirectory.isNull())
       
   380         directories.append(ourDirectory);
       
   381     addQuickTimePluginDirectory(directories);
       
   382     addAdobeAcrobatPluginDirectory(directories);
       
   383     addMozillaPluginDirectories(directories);
       
   384     addWindowsMediaPlayerPluginDirectory(directories);
       
   385     addMacromediaPluginDirectories(directories);
       
   386 
       
   387     return directories;
       
   388 }
       
   389 
       
   390 bool PluginDatabase::isPreferredPluginDirectory(const String& directory)
       
   391 {
       
   392     String ourDirectory = safariPluginsDirectory();
       
   393 
       
   394     if (!ourDirectory.isNull() && !directory.isNull())
       
   395         return ourDirectory == directory;
       
   396 
       
   397     return false;
       
   398 }
       
   399 
       
   400 }