/* 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 "nsLocalHandlerAppWin.h" #include "nsString.h" #include "nsIWindowsRegKey.h" #include "nsILocalFileWin.h" #include "nsComponentManagerUtils.h" static nsresult GetPrettyNameFromFileDescription( const nsCOMPtr& executableOnWindows, const nsString& assignedName, nsString& aName) { nsresult result = NS_ERROR_FAILURE; if (executableOnWindows) { result = executableOnWindows->GetVersionInfoField("FileDescription", aName); if (NS_FAILED(result) || aName.IsEmpty()) { if (!assignedName.IsEmpty()) { aName = assignedName; } else { result = executableOnWindows->GetLeafName(aName); } if (!aName.IsEmpty()) { result = NS_OK; } else { result = NS_ERROR_FAILURE; } } } return result; } static nsresult GetValueFromRegistry(nsString& aName, const nsCOMPtr& appKey, const nsString& registryPath, const nsString& valueName) { nsresult rv = appKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT, registryPath, nsIWindowsRegKey::ACCESS_QUERY_VALUE); if (NS_SUCCEEDED(rv)) { nsAutoString applicationName; if (NS_SUCCEEDED(appKey->ReadStringValue(valueName, applicationName))) { aName = applicationName; return NS_OK; } } return NS_ERROR_FAILURE; }; std::function nsLocalHandlerAppWin::GetPrettyNameOnNonMainThreadCallback() { // Make a copy of executable so that we don't have to worry about any other // threads nsCOMPtr executable; mExecutable->Clone(getter_AddRefs(executable)); // Get the windows interface to the file nsCOMPtr executableOnWindows(do_QueryInterface(executable)); auto appIdOrName = mAppIdOrName; auto assignedName = mName; std::function callback = [assignedName, appIdOrName, executableOnWindows = std::move(executableOnWindows)](nsString& aName) -> nsresult { // On all platforms, we want a human readable name for an application. // For example: msedge -> Microsoft Edge Browser // // This is generated on mac directly in nsLocalHandlerAppMac::GetName. // The auto-test coverage for GetName isn't thorough enough to be // confident that changing GetName on Windows won't cause problems. // // Besides that, this is a potentially slow thing to execute, and making // it asynchronous is preferable. There's a fallback to GetName() in the // nsLocalHandlerApp::PrettyNameAsync to cover Mac and Linux. if (appIdOrName.IsEmpty()) { return GetPrettyNameFromFileDescription(executableOnWindows, assignedName, aName); } nsCOMPtr appKey = do_CreateInstance("@mozilla.org/windows-registry-key;1"); if (!appKey) { return GetPrettyNameFromFileDescription(executableOnWindows, assignedName, aName); } // Check for ApplicationName first. Path: // HKEY_CLASSES_ROOT\${APP_ID}\Application, Value entry: ApplicationName nsresult rv = GetValueFromRegistry(aName, appKey, appIdOrName + u"\\Application"_ns, u"ApplicationName"_ns); if (NS_SUCCEEDED(rv) && !aName.IsEmpty()) { return rv; } // Check for the default on the Applications entry next. // Path: HKEY_CLASSES_ROOT\Applications\${APP_ID}, Value entry: "" // (default) rv = GetValueFromRegistry(aName, appKey, u"Applications\\"_ns + appIdOrName, u""_ns); if (NS_SUCCEEDED(rv) && !aName.IsEmpty()) { return rv; } // Fallthrough to getting the name from the file description return GetPrettyNameFromFileDescription(executableOnWindows, assignedName, aName); }; return callback; }