From 4c580c7aac3b0fa9cb97a56728da712d3a1223e8 Mon Sep 17 00:00:00 2001 From: Fedor Date: Mon, 20 May 2019 09:00:25 +0300 Subject: [PATCH] Revert "Clean up nsOSHelperAppService" --- .../exthandler/win/nsOSHelperAppService.cpp | 192 ++++++++++++------ 1 file changed, 135 insertions(+), 57 deletions(-) diff --git a/uriloader/exthandler/win/nsOSHelperAppService.cpp b/uriloader/exthandler/win/nsOSHelperAppService.cpp index 48b6f1795..f01f3b49b 100644 --- a/uriloader/exthandler/win/nsOSHelperAppService.cpp +++ b/uriloader/exthandler/win/nsOSHelperAppService.cpp @@ -29,6 +29,8 @@ #define LOG(args) MOZ_LOG(mLog, mozilla::LogLevel::Debug, args) // helper methods: forward declarations... +static nsresult GetExtensionFrom4xRegistryInfo(const nsACString& aMimeType, + nsString& aFileExtension); static nsresult GetExtensionFromWindowsMimeDatabase(const nsACString& aMimeType, nsString& aFileExtension); @@ -75,45 +77,79 @@ static nsresult GetExtensionFromWindowsMimeDatabase(const nsACString& aMimeType, return NS_OK; } +// We have a serious problem!! I have this content type and the windows registry only gives me +// helper apps based on extension. Right now, we really don't have a good place to go for +// trying to figure out the extension for a particular mime type....One short term hack is to look +// this information in 4.x (it's stored in the windows regsitry). +static nsresult GetExtensionFrom4xRegistryInfo(const nsACString& aMimeType, + nsString& aFileExtension) +{ + nsCOMPtr regKey = + do_CreateInstance("@mozilla.org/windows-registry-key;1"); + if (!regKey) + return NS_ERROR_NOT_AVAILABLE; + + nsresult rv = regKey-> + Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, + NS_LITERAL_STRING("Software\\Netscape\\Netscape Navigator\\Suffixes"), + nsIWindowsRegKey::ACCESS_QUERY_VALUE); + if (NS_FAILED(rv)) + return NS_ERROR_NOT_AVAILABLE; + + rv = regKey->ReadStringValue(NS_ConvertASCIItoUTF16(aMimeType), + aFileExtension); + if (NS_FAILED(rv)) + return NS_OK; + + aFileExtension.Insert(char16_t('.'), 0); + + // this may be a comma separated list of extensions...just take the + // first one for now... + + int32_t pos = aFileExtension.FindChar(char16_t(',')); + if (pos > 0) { + // we have a comma separated list of types... + // truncate everything after the first comma (including the comma) + aFileExtension.Truncate(pos); + } + + return NS_OK; +} + nsresult nsOSHelperAppService::OSProtocolHandlerExists(const char * aProtocolScheme, bool * aHandlerExists) { // look up the protocol scheme in the windows registry....if we find a match then we have a handler for it... *aHandlerExists = false; if (aProtocolScheme && *aProtocolScheme) { - NS_ENSURE_TRUE(mAppAssoc, NS_ERROR_NOT_AVAILABLE); - wchar_t * pResult = nullptr; - NS_ConvertASCIItoUTF16 scheme(aProtocolScheme); - // We are responsible for freeing returned strings. - HRESULT hr = mAppAssoc->QueryCurrentDefault(scheme.get(), - AT_URLPROTOCOL, AL_EFFECTIVE, - &pResult); - if (SUCCEEDED(hr)) { - CoTaskMemFree(pResult); - // Check the registry to see if it's a valid handler. - nsCOMPtr regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1"); - if (!regKey) { - return NS_ERROR_NOT_AVAILABLE; + // Vista: use new application association interface + if (mAppAssoc) { + wchar_t * pResult = nullptr; + NS_ConvertASCIItoUTF16 scheme(aProtocolScheme); + // We are responsible for freeing returned strings. + HRESULT hr = mAppAssoc->QueryCurrentDefault(scheme.get(), + AT_URLPROTOCOL, AL_EFFECTIVE, + &pResult); + if (SUCCEEDED(hr)) { + CoTaskMemFree(pResult); + *aHandlerExists = true; } + return NS_OK; + } - nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT, - nsDependentString(scheme.get()), - nsIWindowsRegKey::ACCESS_QUERY_VALUE); - if (NS_FAILED(rv)) { - // Open will fail if the registry key path doesn't exist. - return NS_OK; - } - - bool hasValue; - rv = regKey->HasValue(NS_LITERAL_STRING("URL Protocol"), &hasValue); - if (NS_FAILED(rv)) { - return NS_ERROR_FAILURE; - } - if (!hasValue) { - return NS_OK; - } - - *aHandlerExists = true; + HKEY hKey; + LONG err = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, + NS_ConvertASCIItoUTF16(aProtocolScheme).get(), + 0, + KEY_QUERY_VALUE, + &hKey); + if (err == ERROR_SUCCESS) + { + err = ::RegQueryValueExW(hKey, L"URL Protocol", + nullptr, nullptr, nullptr, nullptr); + *aHandlerExists = (err == ERROR_SUCCESS); + // close the key + ::RegCloseKey(hKey); } } @@ -144,21 +180,40 @@ NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription(const nsACString& } } - NS_ENSURE_TRUE(mAppAssoc, NS_ERROR_NOT_AVAILABLE); - wchar_t * pResult = nullptr; - // We are responsible for freeing returned strings. - HRESULT hr = mAppAssoc->QueryCurrentDefault(buf.get(), - AT_URLPROTOCOL, AL_EFFECTIVE, - &pResult); - if (SUCCEEDED(hr)) { - nsCOMPtr app; - nsAutoString appInfo(pResult); - CoTaskMemFree(pResult); - if (NS_SUCCEEDED(GetDefaultAppInfo(appInfo, _retval, getter_AddRefs(app)))) - return NS_OK; + if (mAppAssoc) { + // Vista: use new application association interface + wchar_t * pResult = nullptr; + // We are responsible for freeing returned strings. + HRESULT hr = mAppAssoc->QueryCurrentDefault(buf.get(), + AT_URLPROTOCOL, AL_EFFECTIVE, + &pResult); + if (SUCCEEDED(hr)) { + nsCOMPtr app; + nsAutoString appInfo(pResult); + CoTaskMemFree(pResult); + if (NS_SUCCEEDED(GetDefaultAppInfo(appInfo, _retval, getter_AddRefs(app)))) + return NS_OK; + } + return NS_ERROR_NOT_AVAILABLE; } - return NS_ERROR_NOT_AVAILABLE; + nsCOMPtr app; + GetDefaultAppInfo(buf, _retval, getter_AddRefs(app)); + + if (!_retval.Equals(buf)) + return NS_OK; + + // Fall back to full path + buf.AppendLiteral("\\shell\\open\\command"); + nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT, + buf, + nsIWindowsRegKey::ACCESS_QUERY_VALUE); + if (NS_FAILED(rv)) + return NS_ERROR_NOT_AVAILABLE; + + rv = regKey->ReadStringValue(EmptyString(), _retval); + + return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_NOT_AVAILABLE; } // GetMIMEInfoFromRegistry: This function obtains the values of some of the nsIMIMEInfo @@ -366,18 +421,36 @@ already_AddRefed nsOSHelperAppService::GetByExtension(const nsAFl bool found; // Retrieve the default application for this extension - NS_ENSURE_TRUE(mAppAssoc, nullptr); - nsString assocType(fileExtToUse); - wchar_t * pResult = nullptr; - HRESULT hr = mAppAssoc->QueryCurrentDefault(assocType.get(), - AT_FILEEXTENSION, AL_EFFECTIVE, - &pResult); - if (SUCCEEDED(hr)) { - found = true; - appInfo.Assign(pResult); - CoTaskMemFree(pResult); - } else { - found = false; + if (mAppAssoc) { + // Vista: use the new application association COM interfaces + // for resolving helpers. + nsString assocType(fileExtToUse); + wchar_t * pResult = nullptr; + HRESULT hr = mAppAssoc->QueryCurrentDefault(assocType.get(), + AT_FILEEXTENSION, AL_EFFECTIVE, + &pResult); + if (SUCCEEDED(hr)) { + found = true; + appInfo.Assign(pResult); + CoTaskMemFree(pResult); + } + else { + found = false; + } + } + else + { + nsCOMPtr regKey = + do_CreateInstance("@mozilla.org/windows-registry-key;1"); + if (!regKey) + return nullptr; + nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT, + fileExtToUse, + nsIWindowsRegKey::ACCESS_QUERY_VALUE); + if (NS_SUCCEEDED(rv)) { + found = NS_SUCCEEDED(regKey->ReadStringValue(EmptyString(), + appInfo)); + } } // Bug 358297 - ignore the default handler, force the user to choose app @@ -423,9 +496,14 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS(const nsAC * We'll do extension-based lookup for this type later in this function. */ if (!aMIMEType.LowerCaseEqualsLiteral(APPLICATION_OCTET_STREAM)) { - // try to use the windows mime database to see if there is a mapping to a file extension + // (1) try to use the windows mime database to see if there is a mapping to a file extension + // (2) try to see if we have some left over 4.x registry info we can peek at... GetExtensionFromWindowsMimeDatabase(aMIMEType, fileExtension); LOG(("Windows mime database: extension '%s'\n", fileExtension.get())); + if (fileExtension.IsEmpty()) { + GetExtensionFrom4xRegistryInfo(aMIMEType, fileExtension); + LOG(("4.x Registry: extension '%s'\n", fileExtension.get())); + } } // If we found an extension for the type, do the lookup RefPtr mi;