summaryrefslogtreecommitdiffstats
path: root/dom/plugins/base/nsPluginDirServiceProvider.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/plugins/base/nsPluginDirServiceProvider.cpp')
-rw-r--r--dom/plugins/base/nsPluginDirServiceProvider.cpp448
1 files changed, 448 insertions, 0 deletions
diff --git a/dom/plugins/base/nsPluginDirServiceProvider.cpp b/dom/plugins/base/nsPluginDirServiceProvider.cpp
new file mode 100644
index 000000000..92348c182
--- /dev/null
+++ b/dom/plugins/base/nsPluginDirServiceProvider.cpp
@@ -0,0 +1,448 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsPluginDirServiceProvider.h"
+
+#include "nsCRT.h"
+#include "nsIFile.h"
+#include "nsDependentString.h"
+#include "nsArrayEnumerator.h"
+#include "mozilla/Preferences.h"
+
+#include <windows.h>
+#include "nsIWindowsRegKey.h"
+
+using namespace mozilla;
+
+typedef struct structVer
+{
+ WORD wMajor;
+ WORD wMinor;
+ WORD wRelease;
+ WORD wBuild;
+} verBlock;
+
+static void
+ClearVersion(verBlock *ver)
+{
+ ver->wMajor = 0;
+ ver->wMinor = 0;
+ ver->wRelease = 0;
+ ver->wBuild = 0;
+}
+
+static BOOL
+FileExists(LPCWSTR szFile)
+{
+ return GetFileAttributesW(szFile) != 0xFFFFFFFF;
+}
+
+// Get file version information from a file
+static BOOL
+GetFileVersion(LPCWSTR szFile, verBlock *vbVersion)
+{
+ UINT uLen;
+ UINT dwLen;
+ BOOL bRv;
+ DWORD dwHandle;
+ LPVOID lpData;
+ LPVOID lpBuffer;
+ VS_FIXEDFILEINFO *lpBuffer2;
+
+ ClearVersion(vbVersion);
+ if (FileExists(szFile)) {
+ bRv = TRUE;
+ LPCWSTR lpFilepath = szFile;
+ dwLen = GetFileVersionInfoSizeW(lpFilepath, &dwHandle);
+ lpData = (LPVOID)malloc(dwLen);
+ uLen = 0;
+
+ if (lpData && GetFileVersionInfoW(lpFilepath, dwHandle, dwLen, lpData) != 0) {
+ if (VerQueryValueW(lpData, L"\\", &lpBuffer, &uLen) != 0) {
+ lpBuffer2 = (VS_FIXEDFILEINFO *)lpBuffer;
+
+ vbVersion->wMajor = HIWORD(lpBuffer2->dwFileVersionMS);
+ vbVersion->wMinor = LOWORD(lpBuffer2->dwFileVersionMS);
+ vbVersion->wRelease = HIWORD(lpBuffer2->dwFileVersionLS);
+ vbVersion->wBuild = LOWORD(lpBuffer2->dwFileVersionLS);
+ }
+ }
+
+ free(lpData);
+ } else {
+ /* File does not exist */
+ bRv = FALSE;
+ }
+
+ return bRv;
+}
+
+// Will deep copy ver2 into ver1
+static void
+CopyVersion(verBlock *ver1, verBlock *ver2)
+{
+ ver1->wMajor = ver2->wMajor;
+ ver1->wMinor = ver2->wMinor;
+ ver1->wRelease = ver2->wRelease;
+ ver1->wBuild = ver2->wBuild;
+}
+
+// Convert a string version to a version struct
+static void
+TranslateVersionStr(const WCHAR* szVersion, verBlock *vbVersion)
+{
+ WCHAR* szNum1 = nullptr;
+ WCHAR* szNum2 = nullptr;
+ WCHAR* szNum3 = nullptr;
+ WCHAR* szNum4 = nullptr;
+ WCHAR* szJavaBuild = nullptr;
+
+ WCHAR *strVer = nullptr;
+ if (szVersion) {
+ strVer = wcsdup(szVersion);
+ }
+
+ if (!strVer) {
+ // Out of memory
+ ClearVersion(vbVersion);
+ return;
+ }
+
+ // Java may be using an underscore instead of a dot for the build ID
+ szJavaBuild = wcschr(strVer, '_');
+ if (szJavaBuild) {
+ szJavaBuild[0] = '.';
+ }
+
+#if defined(__MINGW32__)
+ // MSVC 2013 and earlier provided only a non-standard two-argument variant of
+ // wcstok that is generally not thread-safe. For our purposes here, it works
+ // fine, though.
+ auto wcstok = [](wchar_t* strToken, const wchar_t* strDelimit,
+ wchar_t** /*ctx*/) {
+ return ::std::wcstok(strToken, strDelimit);
+ };
+#endif
+
+ wchar_t* ctx = nullptr;
+ szNum1 = wcstok(strVer, L".", &ctx);
+ szNum2 = wcstok(nullptr, L".", &ctx);
+ szNum3 = wcstok(nullptr, L".", &ctx);
+ szNum4 = wcstok(nullptr, L".", &ctx);
+
+ vbVersion->wMajor = szNum1 ? (WORD) _wtoi(szNum1) : 0;
+ vbVersion->wMinor = szNum2 ? (WORD) _wtoi(szNum2) : 0;
+ vbVersion->wRelease = szNum3 ? (WORD) _wtoi(szNum3) : 0;
+ vbVersion->wBuild = szNum4 ? (WORD) _wtoi(szNum4) : 0;
+
+ free(strVer);
+}
+
+// Compare two version struct, return zero if the same
+static int
+CompareVersion(verBlock vbVersionOld, verBlock vbVersionNew)
+{
+ if (vbVersionOld.wMajor > vbVersionNew.wMajor) {
+ return 4;
+ } else if (vbVersionOld.wMajor < vbVersionNew.wMajor) {
+ return -4;
+ }
+
+ if (vbVersionOld.wMinor > vbVersionNew.wMinor) {
+ return 3;
+ } else if (vbVersionOld.wMinor < vbVersionNew.wMinor) {
+ return -3;
+ }
+
+ if (vbVersionOld.wRelease > vbVersionNew.wRelease) {
+ return 2;
+ } else if (vbVersionOld.wRelease < vbVersionNew.wRelease) {
+ return -2;
+ }
+
+ if (vbVersionOld.wBuild > vbVersionNew.wBuild) {
+ return 1;
+ } else if (vbVersionOld.wBuild < vbVersionNew.wBuild) {
+ return -1;
+ }
+
+ /* the versions are all the same */
+ return 0;
+}
+
+//*****************************************************************************
+// nsPluginDirServiceProvider::Constructor/Destructor
+//*****************************************************************************
+
+nsPluginDirServiceProvider::nsPluginDirServiceProvider()
+{
+}
+
+nsPluginDirServiceProvider::~nsPluginDirServiceProvider()
+{
+}
+
+//*****************************************************************************
+// nsPluginDirServiceProvider::nsISupports
+//*****************************************************************************
+
+NS_IMPL_ISUPPORTS(nsPluginDirServiceProvider,
+ nsIDirectoryServiceProvider)
+
+//*****************************************************************************
+// nsPluginDirServiceProvider::nsIDirectoryServiceProvider
+//*****************************************************************************
+
+NS_IMETHODIMP
+nsPluginDirServiceProvider::GetFile(const char *charProp, bool *persistant,
+ nsIFile **_retval)
+{
+ nsCOMPtr<nsIFile> localFile;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ NS_ENSURE_ARG(charProp);
+
+ *_retval = nullptr;
+ *persistant = false;
+
+ nsCOMPtr<nsIWindowsRegKey> regKey =
+ do_CreateInstance("@mozilla.org/windows-registry-key;1");
+ NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
+
+ if (nsCRT::strcmp(charProp, NS_WIN_QUICKTIME_SCAN_KEY) == 0) {
+ nsAdoptingCString strVer = Preferences::GetCString(charProp);
+ if (!strVer) {
+ return NS_ERROR_FAILURE;
+ }
+ verBlock minVer;
+ TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
+
+ // Look for the Quicktime system installation plugins directory
+ verBlock qtVer;
+ ClearVersion(&qtVer);
+
+ // First we need to check the version of Quicktime via checking
+ // the EXE's version table
+ rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
+ NS_LITERAL_STRING("software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\QuickTimePlayer.exe"),
+ nsIWindowsRegKey::ACCESS_READ);
+ if (NS_SUCCEEDED(rv)) {
+ nsAutoString path;
+ rv = regKey->ReadStringValue(NS_LITERAL_STRING(""), path);
+ if (NS_SUCCEEDED(rv)) {
+ GetFileVersion(path.get(), &qtVer);
+ }
+ regKey->Close();
+ }
+ if (CompareVersion(qtVer, minVer) < 0)
+ return rv;
+
+ rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
+ NS_LITERAL_STRING("software\\Apple Computer, Inc.\\QuickTime"),
+ nsIWindowsRegKey::ACCESS_READ);
+ if (NS_SUCCEEDED(rv)) {
+ nsAutoString path;
+ rv = regKey->ReadStringValue(NS_LITERAL_STRING("InstallDir"), path);
+ if (NS_SUCCEEDED(rv)) {
+ path += NS_LITERAL_STRING("\\Plugins");
+ rv = NS_NewLocalFile(path, true,
+ getter_AddRefs(localFile));
+ }
+ }
+ } else if (nsCRT::strcmp(charProp, NS_WIN_WMP_SCAN_KEY) == 0) {
+ nsAdoptingCString strVer = Preferences::GetCString(charProp);
+ if (!strVer) {
+ return NS_ERROR_FAILURE;
+ }
+ verBlock minVer;
+ TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
+
+ // Look for Windows Media Player system installation plugins directory
+ verBlock wmpVer;
+ ClearVersion(&wmpVer);
+
+ // First we need to check the version of WMP
+ rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
+ NS_LITERAL_STRING("software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wmplayer.exe"),
+ nsIWindowsRegKey::ACCESS_READ);
+ if (NS_SUCCEEDED(rv)) {
+ nsAutoString path;
+ rv = regKey->ReadStringValue(NS_LITERAL_STRING(""), path);
+ if (NS_SUCCEEDED(rv)) {
+ GetFileVersion(path.get(), &wmpVer);
+ }
+ regKey->Close();
+ }
+ if (CompareVersion(wmpVer, minVer) < 0)
+ return rv;
+
+ rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
+ NS_LITERAL_STRING("software\\Microsoft\\MediaPlayer"),
+ nsIWindowsRegKey::ACCESS_READ);
+ if (NS_SUCCEEDED(rv)) {
+ nsAutoString path;
+ rv = regKey->ReadStringValue(NS_LITERAL_STRING("Installation Directory"),
+ path);
+ if (NS_SUCCEEDED(rv)) {
+ rv = NS_NewLocalFile(path, true,
+ getter_AddRefs(localFile));
+ }
+ }
+ } else if (nsCRT::strcmp(charProp, NS_WIN_ACROBAT_SCAN_KEY) == 0) {
+ nsAdoptingCString strVer = Preferences::GetCString(charProp);
+ if (!strVer) {
+ return NS_ERROR_FAILURE;
+ }
+
+ verBlock minVer;
+ TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
+
+ // Look for Adobe Acrobat system installation plugins directory
+ verBlock maxVer;
+ ClearVersion(&maxVer);
+
+ nsAutoString newestPath;
+
+ rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
+ NS_LITERAL_STRING("software\\Adobe\\Acrobat Reader"),
+ nsIWindowsRegKey::ACCESS_READ);
+ if (NS_FAILED(rv)) {
+ rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
+ NS_LITERAL_STRING("software\\Adobe\\Adobe Acrobat"),
+ nsIWindowsRegKey::ACCESS_READ);
+ if (NS_FAILED(rv)) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ // We must enumerate through the keys because what if there is
+ // more than one version?
+ uint32_t childCount = 0;
+ regKey->GetChildCount(&childCount);
+
+ for (uint32_t index = 0; index < childCount; ++index) {
+ nsAutoString childName;
+ rv = regKey->GetChildName(index, childName);
+ if (NS_SUCCEEDED(rv)) {
+ verBlock curVer;
+ TranslateVersionStr(childName.get(), &curVer);
+
+ childName += NS_LITERAL_STRING("\\InstallPath");
+
+ nsCOMPtr<nsIWindowsRegKey> childKey;
+ rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE,
+ getter_AddRefs(childKey));
+ if (NS_SUCCEEDED(rv)) {
+ // We have a sub key
+ nsAutoString path;
+ rv = childKey->ReadStringValue(NS_LITERAL_STRING(""), path);
+ if (NS_SUCCEEDED(rv)) {
+ if (CompareVersion(curVer, maxVer) >= 0 &&
+ CompareVersion(curVer, minVer) >= 0) {
+ newestPath = path;
+ CopyVersion(&maxVer, &curVer);
+ }
+ }
+ }
+ }
+ }
+
+ if (!newestPath.IsEmpty()) {
+ newestPath += NS_LITERAL_STRING("\\browser");
+ rv = NS_NewLocalFile(newestPath, true,
+ getter_AddRefs(localFile));
+ }
+ }
+
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ localFile.forget(_retval);
+ return NS_OK;
+}
+
+nsresult
+nsPluginDirServiceProvider::GetPLIDDirectories(nsISimpleEnumerator **aEnumerator)
+{
+ NS_ENSURE_ARG_POINTER(aEnumerator);
+ *aEnumerator = nullptr;
+
+ nsCOMArray<nsIFile> dirs;
+
+ GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, dirs);
+ GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, dirs);
+
+ return NS_NewArrayEnumerator(aEnumerator, dirs);
+}
+
+nsresult
+nsPluginDirServiceProvider::GetPLIDDirectoriesWithRootKey(uint32_t aKey, nsCOMArray<nsIFile> &aDirs)
+{
+ nsCOMPtr<nsIWindowsRegKey> regKey =
+ do_CreateInstance("@mozilla.org/windows-registry-key;1");
+ NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
+
+ nsresult rv = regKey->Open(aKey,
+ NS_LITERAL_STRING("Software\\MozillaPlugins"),
+ nsIWindowsRegKey::ACCESS_READ);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ uint32_t childCount = 0;
+ regKey->GetChildCount(&childCount);
+
+ for (uint32_t index = 0; index < childCount; ++index) {
+ nsAutoString childName;
+ rv = regKey->GetChildName(index, childName);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIWindowsRegKey> childKey;
+ rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE,
+ getter_AddRefs(childKey));
+ if (NS_SUCCEEDED(rv) && childKey) {
+ nsAutoString path;
+ rv = childKey->ReadStringValue(NS_LITERAL_STRING("Path"), path);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIFile> localFile;
+ if (NS_SUCCEEDED(NS_NewLocalFile(path, true,
+ getter_AddRefs(localFile))) &&
+ localFile) {
+ // Some vendors use a path directly to the DLL so chop off
+ // the filename
+ bool isDir = false;
+ if (NS_SUCCEEDED(localFile->IsDirectory(&isDir)) && !isDir) {
+ nsCOMPtr<nsIFile> temp;
+ localFile->GetParent(getter_AddRefs(temp));
+ if (temp)
+ localFile = temp;
+ }
+
+ // Now we check to make sure it's actually on disk and
+ // To see if we already have this directory in the array
+ bool isFileThere = false;
+ bool isDupEntry = false;
+ if (NS_SUCCEEDED(localFile->Exists(&isFileThere)) && isFileThere) {
+ int32_t c = aDirs.Count();
+ for (int32_t i = 0; i < c; i++) {
+ nsIFile *dup = static_cast<nsIFile*>(aDirs[i]);
+ if (dup &&
+ NS_SUCCEEDED(dup->Equals(localFile, &isDupEntry)) &&
+ isDupEntry) {
+ break;
+ }
+ }
+
+ if (!isDupEntry) {
+ aDirs.AppendObject(localFile);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return NS_OK;
+}