dom/plugins/base/nsPluginDirServiceProvider.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/plugins/base/nsPluginDirServiceProvider.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,438 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "nsPluginDirServiceProvider.h"
    1.10 +
    1.11 +#include "nsCRT.h"
    1.12 +#include "nsIFile.h"
    1.13 +#include "nsDependentString.h"
    1.14 +#include "nsArrayEnumerator.h"
    1.15 +#include "mozilla/Preferences.h"
    1.16 +
    1.17 +#include <windows.h>
    1.18 +#include "nsIWindowsRegKey.h"
    1.19 +
    1.20 +using namespace mozilla;
    1.21 +
    1.22 +typedef struct structVer
    1.23 +{
    1.24 +  WORD wMajor;
    1.25 +  WORD wMinor;
    1.26 +  WORD wRelease;
    1.27 +  WORD wBuild;
    1.28 +} verBlock;
    1.29 +
    1.30 +static void
    1.31 +ClearVersion(verBlock *ver)
    1.32 +{
    1.33 +  ver->wMajor   = 0;
    1.34 +  ver->wMinor   = 0;
    1.35 +  ver->wRelease = 0;
    1.36 +  ver->wBuild   = 0;
    1.37 +}
    1.38 +
    1.39 +static BOOL
    1.40 +FileExists(LPCWSTR szFile)
    1.41 +{
    1.42 +  return GetFileAttributesW(szFile) != 0xFFFFFFFF;
    1.43 +}
    1.44 +
    1.45 +// Get file version information from a file
    1.46 +static BOOL
    1.47 +GetFileVersion(LPCWSTR szFile, verBlock *vbVersion)
    1.48 +{
    1.49 +  UINT              uLen;
    1.50 +  UINT              dwLen;
    1.51 +  BOOL              bRv;
    1.52 +  DWORD             dwHandle;
    1.53 +  LPVOID            lpData;
    1.54 +  LPVOID            lpBuffer;
    1.55 +  VS_FIXEDFILEINFO  *lpBuffer2;
    1.56 +
    1.57 +  ClearVersion(vbVersion);
    1.58 +  if (FileExists(szFile)) {
    1.59 +    bRv    = TRUE;
    1.60 +    LPCWSTR lpFilepath = szFile;
    1.61 +    dwLen  = GetFileVersionInfoSizeW(lpFilepath, &dwHandle);
    1.62 +    lpData = (LPVOID)malloc(dwLen);
    1.63 +    uLen   = 0;
    1.64 +
    1.65 +    if (lpData && GetFileVersionInfoW(lpFilepath, dwHandle, dwLen, lpData) != 0) {
    1.66 +      if (VerQueryValueW(lpData, L"\\", &lpBuffer, &uLen) != 0) {
    1.67 +        lpBuffer2 = (VS_FIXEDFILEINFO *)lpBuffer;
    1.68 +
    1.69 +        vbVersion->wMajor   = HIWORD(lpBuffer2->dwFileVersionMS);
    1.70 +        vbVersion->wMinor   = LOWORD(lpBuffer2->dwFileVersionMS);
    1.71 +        vbVersion->wRelease = HIWORD(lpBuffer2->dwFileVersionLS);
    1.72 +        vbVersion->wBuild   = LOWORD(lpBuffer2->dwFileVersionLS);
    1.73 +      }
    1.74 +    }
    1.75 +
    1.76 +    free(lpData);
    1.77 +  } else {
    1.78 +    /* File does not exist */
    1.79 +    bRv = FALSE;
    1.80 +  }
    1.81 +
    1.82 +  return bRv;
    1.83 +}
    1.84 +
    1.85 +// Will deep copy ver2 into ver1
    1.86 +static void
    1.87 +CopyVersion(verBlock *ver1, verBlock *ver2)
    1.88 +{
    1.89 +  ver1->wMajor   = ver2->wMajor;
    1.90 +  ver1->wMinor   = ver2->wMinor;
    1.91 +  ver1->wRelease = ver2->wRelease;
    1.92 +  ver1->wBuild   = ver2->wBuild;
    1.93 +}
    1.94 +
    1.95 +// Convert a string version to a version struct
    1.96 +static void
    1.97 +TranslateVersionStr(const WCHAR* szVersion, verBlock *vbVersion)
    1.98 +{
    1.99 +  WCHAR* szNum1 = nullptr;
   1.100 +  WCHAR* szNum2 = nullptr;
   1.101 +  WCHAR* szNum3 = nullptr;
   1.102 +  WCHAR* szNum4 = nullptr;
   1.103 +  WCHAR* szJavaBuild = nullptr;
   1.104 +
   1.105 +  WCHAR *strVer = nullptr;
   1.106 +  if (szVersion) {
   1.107 +    strVer = wcsdup(szVersion);
   1.108 +  }
   1.109 +
   1.110 +  if (!strVer) {
   1.111 +    // Out of memory
   1.112 +    ClearVersion(vbVersion);
   1.113 +    return;
   1.114 +  }
   1.115 +
   1.116 +  // Java may be using an underscore instead of a dot for the build ID
   1.117 +  szJavaBuild = wcschr(strVer, '_');
   1.118 +  if (szJavaBuild) {
   1.119 +    szJavaBuild[0] = '.';
   1.120 +  }
   1.121 +
   1.122 +  szNum1 = wcstok(strVer,  L".");
   1.123 +  szNum2 = wcstok(nullptr, L".");
   1.124 +  szNum3 = wcstok(nullptr, L".");
   1.125 +  szNum4 = wcstok(nullptr, L".");
   1.126 +
   1.127 +  vbVersion->wMajor   = szNum1 ? (WORD) _wtoi(szNum1) : 0;
   1.128 +  vbVersion->wMinor   = szNum2 ? (WORD) _wtoi(szNum2) : 0;
   1.129 +  vbVersion->wRelease = szNum3 ? (WORD) _wtoi(szNum3) : 0;
   1.130 +  vbVersion->wBuild   = szNum4 ? (WORD) _wtoi(szNum4) : 0;
   1.131 +
   1.132 +  free(strVer);
   1.133 +}
   1.134 +
   1.135 +// Compare two version struct, return zero if the same
   1.136 +static int
   1.137 +CompareVersion(verBlock vbVersionOld, verBlock vbVersionNew)
   1.138 +{
   1.139 +  if (vbVersionOld.wMajor > vbVersionNew.wMajor) {
   1.140 +    return 4;
   1.141 +  } else if (vbVersionOld.wMajor < vbVersionNew.wMajor) {
   1.142 +    return -4;
   1.143 +  }
   1.144 +
   1.145 +  if (vbVersionOld.wMinor > vbVersionNew.wMinor) {
   1.146 +    return 3;
   1.147 +  } else if (vbVersionOld.wMinor < vbVersionNew.wMinor) {
   1.148 +    return -3;
   1.149 +  }
   1.150 +
   1.151 +  if (vbVersionOld.wRelease > vbVersionNew.wRelease) {
   1.152 +    return 2;
   1.153 +  } else if (vbVersionOld.wRelease < vbVersionNew.wRelease) {
   1.154 +    return -2;
   1.155 +  }
   1.156 +
   1.157 +  if (vbVersionOld.wBuild > vbVersionNew.wBuild) {
   1.158 +    return 1;
   1.159 +  } else if (vbVersionOld.wBuild < vbVersionNew.wBuild) {
   1.160 +    return -1;
   1.161 +  }
   1.162 +
   1.163 +  /* the versions are all the same */
   1.164 +  return 0;
   1.165 +}
   1.166 +
   1.167 +//*****************************************************************************
   1.168 +// nsPluginDirServiceProvider::Constructor/Destructor
   1.169 +//*****************************************************************************
   1.170 +
   1.171 +nsPluginDirServiceProvider::nsPluginDirServiceProvider()
   1.172 +{
   1.173 +}
   1.174 +
   1.175 +nsPluginDirServiceProvider::~nsPluginDirServiceProvider()
   1.176 +{
   1.177 +}
   1.178 +
   1.179 +//*****************************************************************************
   1.180 +// nsPluginDirServiceProvider::nsISupports
   1.181 +//*****************************************************************************
   1.182 +
   1.183 +NS_IMPL_ISUPPORTS(nsPluginDirServiceProvider,
   1.184 +                  nsIDirectoryServiceProvider)
   1.185 +
   1.186 +//*****************************************************************************
   1.187 +// nsPluginDirServiceProvider::nsIDirectoryServiceProvider
   1.188 +//*****************************************************************************
   1.189 +
   1.190 +NS_IMETHODIMP
   1.191 +nsPluginDirServiceProvider::GetFile(const char *charProp, bool *persistant,
   1.192 +                                    nsIFile **_retval)
   1.193 +{
   1.194 +  nsCOMPtr<nsIFile>  localFile;
   1.195 +  nsresult rv = NS_ERROR_FAILURE;
   1.196 +
   1.197 +  NS_ENSURE_ARG(charProp);
   1.198 +
   1.199 +  *_retval = nullptr;
   1.200 +  *persistant = false;
   1.201 +
   1.202 +  nsCOMPtr<nsIWindowsRegKey> regKey =
   1.203 +    do_CreateInstance("@mozilla.org/windows-registry-key;1");
   1.204 +  NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
   1.205 +
   1.206 +  if (nsCRT::strcmp(charProp, NS_WIN_QUICKTIME_SCAN_KEY) == 0) {
   1.207 +    nsAdoptingCString strVer = Preferences::GetCString(charProp);
   1.208 +    if (!strVer) {
   1.209 +      return NS_ERROR_FAILURE;
   1.210 +    }
   1.211 +    verBlock minVer;
   1.212 +    TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
   1.213 +
   1.214 +    // Look for the Quicktime system installation plugins directory
   1.215 +    verBlock qtVer;
   1.216 +    ClearVersion(&qtVer);
   1.217 +
   1.218 +    // First we need to check the version of Quicktime via checking
   1.219 +    // the EXE's version table
   1.220 +    rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
   1.221 +                      NS_LITERAL_STRING("software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\QuickTimePlayer.exe"),
   1.222 +                      nsIWindowsRegKey::ACCESS_READ);
   1.223 +    if (NS_SUCCEEDED(rv)) {
   1.224 +      nsAutoString path;
   1.225 +      rv = regKey->ReadStringValue(NS_LITERAL_STRING(""), path);
   1.226 +      if (NS_SUCCEEDED(rv)) {
   1.227 +        GetFileVersion(path.get(), &qtVer);
   1.228 +      }
   1.229 +      regKey->Close();
   1.230 +    }
   1.231 +    if (CompareVersion(qtVer, minVer) < 0)
   1.232 +      return rv;
   1.233 +
   1.234 +    rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
   1.235 +                      NS_LITERAL_STRING("software\\Apple Computer, Inc.\\QuickTime"),
   1.236 +                      nsIWindowsRegKey::ACCESS_READ);
   1.237 +    if (NS_SUCCEEDED(rv)) {
   1.238 +      nsAutoString path;
   1.239 +      rv = regKey->ReadStringValue(NS_LITERAL_STRING("InstallDir"), path);
   1.240 +      if (NS_SUCCEEDED(rv)) {
   1.241 +        path += NS_LITERAL_STRING("\\Plugins");
   1.242 +        rv = NS_NewLocalFile(path, true,
   1.243 +                             getter_AddRefs(localFile));
   1.244 +      }
   1.245 +    }
   1.246 +  } else if (nsCRT::strcmp(charProp, NS_WIN_WMP_SCAN_KEY) == 0) {
   1.247 +    nsAdoptingCString strVer = Preferences::GetCString(charProp);
   1.248 +    if (!strVer) {
   1.249 +      return NS_ERROR_FAILURE;
   1.250 +    }
   1.251 +    verBlock minVer;
   1.252 +    TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
   1.253 +
   1.254 +    // Look for Windows Media Player system installation plugins directory
   1.255 +    verBlock wmpVer;
   1.256 +    ClearVersion(&wmpVer);
   1.257 +
   1.258 +    // First we need to check the version of WMP
   1.259 +    rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
   1.260 +                      NS_LITERAL_STRING("software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wmplayer.exe"),
   1.261 +                      nsIWindowsRegKey::ACCESS_READ);
   1.262 +    if (NS_SUCCEEDED(rv)) {
   1.263 +      nsAutoString path;
   1.264 +      rv = regKey->ReadStringValue(NS_LITERAL_STRING(""), path);
   1.265 +      if (NS_SUCCEEDED(rv)) {
   1.266 +        GetFileVersion(path.get(), &wmpVer);
   1.267 +      }
   1.268 +      regKey->Close();
   1.269 +    }
   1.270 +    if (CompareVersion(wmpVer, minVer) < 0)
   1.271 +      return rv;
   1.272 +
   1.273 +    rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
   1.274 +                      NS_LITERAL_STRING("software\\Microsoft\\MediaPlayer"),
   1.275 +                      nsIWindowsRegKey::ACCESS_READ);
   1.276 +    if (NS_SUCCEEDED(rv)) {
   1.277 +      nsAutoString path;
   1.278 +      rv = regKey->ReadStringValue(NS_LITERAL_STRING("Installation Directory"),
   1.279 +                                   path);
   1.280 +      if (NS_SUCCEEDED(rv)) {
   1.281 +        rv = NS_NewLocalFile(path, true,
   1.282 +                             getter_AddRefs(localFile));
   1.283 +      }
   1.284 +    }
   1.285 +  } else if (nsCRT::strcmp(charProp, NS_WIN_ACROBAT_SCAN_KEY) == 0) {
   1.286 +    nsAdoptingCString strVer = Preferences::GetCString(charProp);
   1.287 +    if (!strVer) {
   1.288 +      return NS_ERROR_FAILURE;
   1.289 +    }
   1.290 +
   1.291 +    verBlock minVer;
   1.292 +    TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
   1.293 +
   1.294 +    // Look for Adobe Acrobat system installation plugins directory
   1.295 +    verBlock maxVer;
   1.296 +    ClearVersion(&maxVer);
   1.297 +
   1.298 +    nsAutoString newestPath;
   1.299 +
   1.300 +    rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
   1.301 +                      NS_LITERAL_STRING("software\\Adobe\\Acrobat Reader"),
   1.302 +                      nsIWindowsRegKey::ACCESS_READ);
   1.303 +    if (NS_FAILED(rv)) {
   1.304 +      rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
   1.305 +                        NS_LITERAL_STRING("software\\Adobe\\Adobe Acrobat"),
   1.306 +                        nsIWindowsRegKey::ACCESS_READ);
   1.307 +      if (NS_FAILED(rv)) {
   1.308 +        return NS_ERROR_FAILURE;
   1.309 +      }
   1.310 +    }
   1.311 +
   1.312 +    // We must enumerate through the keys because what if there is
   1.313 +    // more than one version?
   1.314 +    uint32_t childCount = 0;
   1.315 +    regKey->GetChildCount(&childCount);
   1.316 +
   1.317 +    for (uint32_t index = 0; index < childCount; ++index) {
   1.318 +      nsAutoString childName;
   1.319 +      rv = regKey->GetChildName(index, childName);
   1.320 +      if (NS_SUCCEEDED(rv)) {
   1.321 +        verBlock curVer;
   1.322 +        TranslateVersionStr(childName.get(), &curVer);
   1.323 +
   1.324 +        childName += NS_LITERAL_STRING("\\InstallPath");
   1.325 +
   1.326 +        nsCOMPtr<nsIWindowsRegKey> childKey;
   1.327 +        rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE,
   1.328 +                               getter_AddRefs(childKey));
   1.329 +        if (NS_SUCCEEDED(rv)) {
   1.330 +          // We have a sub key
   1.331 +          nsAutoString path;
   1.332 +          rv = childKey->ReadStringValue(NS_LITERAL_STRING(""), path);
   1.333 +          if (NS_SUCCEEDED(rv)) {
   1.334 +            if (CompareVersion(curVer, maxVer) >= 0 &&
   1.335 +                CompareVersion(curVer, minVer) >= 0) {
   1.336 +              newestPath = path;
   1.337 +              CopyVersion(&maxVer, &curVer);
   1.338 +            }
   1.339 +          }
   1.340 +        }
   1.341 +      }
   1.342 +    }
   1.343 +
   1.344 +    if (!newestPath.IsEmpty()) {
   1.345 +      newestPath += NS_LITERAL_STRING("\\browser");
   1.346 +      rv = NS_NewLocalFile(newestPath, true,
   1.347 +                           getter_AddRefs(localFile));
   1.348 +    }
   1.349 +  }
   1.350 +
   1.351 +  if (NS_FAILED(rv)) {
   1.352 +    return rv;
   1.353 +  }
   1.354 +
   1.355 +  localFile.forget(_retval);
   1.356 +  return NS_OK;
   1.357 +}
   1.358 +
   1.359 +nsresult
   1.360 +nsPluginDirServiceProvider::GetPLIDDirectories(nsISimpleEnumerator **aEnumerator)
   1.361 +{
   1.362 +  NS_ENSURE_ARG_POINTER(aEnumerator);
   1.363 +  *aEnumerator = nullptr;
   1.364 +
   1.365 +  nsCOMArray<nsIFile> dirs;
   1.366 +
   1.367 +  GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, dirs);
   1.368 +  GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, dirs);
   1.369 +
   1.370 +  return NS_NewArrayEnumerator(aEnumerator, dirs);
   1.371 +}
   1.372 +
   1.373 +nsresult
   1.374 +nsPluginDirServiceProvider::GetPLIDDirectoriesWithRootKey(uint32_t aKey, nsCOMArray<nsIFile> &aDirs)
   1.375 +{
   1.376 +  nsCOMPtr<nsIWindowsRegKey> regKey =
   1.377 +    do_CreateInstance("@mozilla.org/windows-registry-key;1");
   1.378 +  NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
   1.379 +
   1.380 +  nsresult rv = regKey->Open(aKey,
   1.381 +                             NS_LITERAL_STRING("Software\\MozillaPlugins"),
   1.382 +                             nsIWindowsRegKey::ACCESS_READ);
   1.383 +  if (NS_FAILED(rv)) {
   1.384 +    return rv;
   1.385 +  }
   1.386 +
   1.387 +  uint32_t childCount = 0;
   1.388 +  regKey->GetChildCount(&childCount);
   1.389 +
   1.390 +  for (uint32_t index = 0; index < childCount; ++index) {
   1.391 +    nsAutoString childName;
   1.392 +    rv = regKey->GetChildName(index, childName);
   1.393 +    if (NS_SUCCEEDED(rv)) {
   1.394 +      nsCOMPtr<nsIWindowsRegKey> childKey;
   1.395 +      rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE,
   1.396 +                             getter_AddRefs(childKey));
   1.397 +      if (NS_SUCCEEDED(rv) && childKey) {
   1.398 +        nsAutoString path;
   1.399 +        rv = childKey->ReadStringValue(NS_LITERAL_STRING("Path"), path);
   1.400 +        if (NS_SUCCEEDED(rv)) {
   1.401 +          nsCOMPtr<nsIFile> localFile;
   1.402 +          if (NS_SUCCEEDED(NS_NewLocalFile(path, true,
   1.403 +                                           getter_AddRefs(localFile))) &&
   1.404 +              localFile) {
   1.405 +            // Some vendors use a path directly to the DLL so chop off
   1.406 +            // the filename
   1.407 +            bool isDir = false;
   1.408 +            if (NS_SUCCEEDED(localFile->IsDirectory(&isDir)) && !isDir) {
   1.409 +              nsCOMPtr<nsIFile> temp;
   1.410 +              localFile->GetParent(getter_AddRefs(temp));
   1.411 +              if (temp)
   1.412 +                localFile = temp;
   1.413 +            }
   1.414 +
   1.415 +            // Now we check to make sure it's actually on disk and
   1.416 +            // To see if we already have this directory in the array
   1.417 +            bool isFileThere = false;
   1.418 +            bool isDupEntry = false;
   1.419 +            if (NS_SUCCEEDED(localFile->Exists(&isFileThere)) && isFileThere) {
   1.420 +              int32_t c = aDirs.Count();
   1.421 +              for (int32_t i = 0; i < c; i++) {
   1.422 +                nsIFile *dup = static_cast<nsIFile*>(aDirs[i]);
   1.423 +                if (dup &&
   1.424 +                    NS_SUCCEEDED(dup->Equals(localFile, &isDupEntry)) &&
   1.425 +                    isDupEntry) {
   1.426 +                  break;
   1.427 +                }
   1.428 +              }
   1.429 +
   1.430 +              if (!isDupEntry) {
   1.431 +                aDirs.AppendObject(localFile);
   1.432 +              }
   1.433 +            }
   1.434 +          }
   1.435 +        }
   1.436 +      }
   1.437 +    }
   1.438 +  }
   1.439 +  return NS_OK;
   1.440 +}
   1.441 +

mercurial