diff options
Diffstat (limited to 'uriloader/exthandler')
-rw-r--r-- | uriloader/exthandler/HandlerServiceParent.cpp | 4 | ||||
-rw-r--r-- | uriloader/exthandler/android/nsMIMEInfoAndroid.cpp | 5 | ||||
-rw-r--r-- | uriloader/exthandler/moz.build | 1 | ||||
-rw-r--r-- | uriloader/exthandler/nsIContentDispatchChooser.idl | 2 | ||||
-rw-r--r-- | uriloader/exthandler/nsIExternalProtocolService.idl | 6 | ||||
-rw-r--r-- | uriloader/exthandler/nsLocalHandlerApp.cpp | 98 | ||||
-rw-r--r-- | uriloader/exthandler/nsLocalHandlerApp.h | 10 | ||||
-rw-r--r-- | uriloader/exthandler/nsMIMEInfoImpl.cpp | 15 | ||||
-rw-r--r-- | uriloader/exthandler/nsMIMEInfoImpl.h | 2 | ||||
-rw-r--r-- | uriloader/exthandler/tests/unit/test_getFromTypeAndExtension.js | 122 | ||||
-rw-r--r-- | uriloader/exthandler/tests/unit/xpcshell.toml | 1 | ||||
-rw-r--r-- | uriloader/exthandler/unix/nsMIMEInfoUnix.cpp | 13 | ||||
-rw-r--r-- | uriloader/exthandler/unix/nsMIMEInfoUnix.h | 1 | ||||
-rw-r--r-- | uriloader/exthandler/win/nsLocalHandlerAppWin.cpp | 119 | ||||
-rw-r--r-- | uriloader/exthandler/win/nsLocalHandlerAppWin.h | 34 | ||||
-rw-r--r-- | uriloader/exthandler/win/nsMIMEInfoWin.cpp | 31 | ||||
-rw-r--r-- | uriloader/exthandler/win/nsMIMEInfoWin.h | 3 |
17 files changed, 454 insertions, 13 deletions
diff --git a/uriloader/exthandler/HandlerServiceParent.cpp b/uriloader/exthandler/HandlerServiceParent.cpp index ab77657dd5..1c83d9628f 100644 --- a/uriloader/exthandler/HandlerServiceParent.cpp +++ b/uriloader/exthandler/HandlerServiceParent.cpp @@ -110,6 +110,10 @@ NS_IMETHODIMP ProxyHandlerInfo::GetDefaultDescription( return NS_ERROR_NOT_IMPLEMENTED; } +NS_IMETHODIMP ProxyHandlerInfo::GetDefaultExecutable(nsIFile** aExecutable) { + return NS_ERROR_NOT_IMPLEMENTED; +} + /* void launchWithURI (in nsIURI aURI, [optional] in BrowsingContext aBrowsingContext); */ NS_IMETHODIMP ProxyHandlerInfo::LaunchWithURI( diff --git a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp index 86049a55fb..388a378308 100644 --- a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp +++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp @@ -125,6 +125,11 @@ nsMIMEInfoAndroid::GetDefaultDescription(nsAString& aDesc) { } NS_IMETHODIMP +nsMIMEInfoAndroid::GetDefaultExecutable(nsIFile** aExecutable) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsMIMEInfoAndroid::LaunchWithURI( nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) { return mPrefApp->LaunchWithURI(aURI, aBrowsingContext); diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build index cb96c690a6..e9009eb063 100644 --- a/uriloader/exthandler/moz.build +++ b/uriloader/exthandler/moz.build @@ -95,6 +95,7 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "android": ] elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows": UNIFIED_SOURCES += [ + "win/nsLocalHandlerAppWin.cpp", "win/nsMIMEInfoWin.cpp", ] diff --git a/uriloader/exthandler/nsIContentDispatchChooser.idl b/uriloader/exthandler/nsIContentDispatchChooser.idl index 00d61e575b..c0130038d4 100644 --- a/uriloader/exthandler/nsIContentDispatchChooser.idl +++ b/uriloader/exthandler/nsIContentDispatchChooser.idl @@ -36,5 +36,5 @@ interface nsIContentDispatchChooser : nsISupports { in nsIURI aURI, in nsIPrincipal aTriggeringPrincipal, in BrowsingContext aBrowsingContext, - [optional] in bool aWasTriggeredExternally); + [optional] in boolean aWasTriggeredExternally); }; diff --git a/uriloader/exthandler/nsIExternalProtocolService.idl b/uriloader/exthandler/nsIExternalProtocolService.idl index 7d714035e6..5c544a967d 100644 --- a/uriloader/exthandler/nsIExternalProtocolService.idl +++ b/uriloader/exthandler/nsIExternalProtocolService.idl @@ -129,8 +129,8 @@ interface nsIExternalProtocolService : nsISupports [optional] in nsIPrincipal aTriggeringPrincipal, [optional] in nsIPrincipal aRedirectPrincipal, [optional] in BrowsingContext aBrowsingContext, - [optional] in bool aWasTriggeredExternally, - [optional] in bool aHasValidUserGestureActivation); + [optional] in boolean aWasTriggeredExternally, + [optional] in boolean aHasValidUserGestureActivation); /** * Gets a human-readable description for the application responsible for @@ -151,5 +151,5 @@ interface nsIExternalProtocolService : nsISupports * * @param aScheme The scheme to look up. For example, "mms". */ - bool isCurrentAppOSDefaultForProtocol(in AUTF8String aScheme); + boolean isCurrentAppOSDefaultForProtocol(in AUTF8String aScheme); }; diff --git a/uriloader/exthandler/nsLocalHandlerApp.cpp b/uriloader/exthandler/nsLocalHandlerApp.cpp index 6212d2aeb4..fa3f27758f 100644 --- a/uriloader/exthandler/nsLocalHandlerApp.cpp +++ b/uriloader/exthandler/nsLocalHandlerApp.cpp @@ -8,11 +8,15 @@ #include "nsIURI.h" #include "nsIProcess.h" #include "nsComponentManagerUtils.h" +#include "mozilla/dom/Promise.h" +#include "nsProxyRelease.h" // XXX why does nsMIMEInfoImpl have a threadsafe nsISupports? do we need one // here too? NS_IMPL_ISUPPORTS(nsLocalHandlerApp, nsILocalHandlerApp, nsIHandlerApp) +using namespace mozilla; + //////////////////////////////////////////////////////////////////////////////// //// nsIHandlerApp @@ -28,6 +32,100 @@ NS_IMETHODIMP nsLocalHandlerApp::GetName(nsAString& aName) { return NS_OK; } +/** + * This method returns a std::function that will be executed on a thread other + * than the main thread. To facilitate things, it should effectively be a global + * function that does not maintain a reference to the this pointer. There should + * be no reference to any objects that will be shared across threads. Sub-class + * implementations should make local copies of everything they need and capture + * those in the callback. + */ +std::function<nsresult(nsString&)> +nsLocalHandlerApp::GetPrettyNameOnNonMainThreadCallback() { + nsString name; + + // Calculate the name now, on the main thread, so as to avoid + // doing anything with the this pointer on the other thread + auto result = GetName(name); + + return [name, result](nsString& aName) -> nsresult { + aName = name; + return result; + }; +} + +NS_IMETHODIMP +nsLocalHandlerApp::PrettyNameAsync(JSContext* aCx, dom::Promise** aPromise) { + NS_ENSURE_ARG_POINTER(aPromise); + + *aPromise = nullptr; + + if (!mExecutable) { + return NS_ERROR_FAILURE; + } + + nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx); + if (NS_WARN_IF(!global)) { + return NS_ERROR_FAILURE; + } + + ErrorResult err; + RefPtr<dom::Promise> outer = dom::Promise::Create(global, err); + if (NS_WARN_IF(err.Failed())) { + return err.StealNSResult(); + } + + outer.forget(aPromise); + + nsAutoString executablePath; + nsresult result = mExecutable->GetPath(executablePath); + + if (NS_FAILED(result) || executablePath.IsEmpty()) { + (*aPromise)->MaybeReject(result); + return NS_OK; + } + + nsMainThreadPtrHandle<dom::Promise> promiseHolder( + new nsMainThreadPtrHolder<dom::Promise>( + "nsLocalHandlerApp::prettyExecutableName Promise", *aPromise)); + + auto prettyNameGetter = GetPrettyNameOnNonMainThreadCallback(); + + result = NS_DispatchBackgroundTask( + NS_NewRunnableFunction( + __func__, + [promiseHolder /* can't move this because if the dispatch fails, we + call reject on the promiseHolder */ + , + prettyNameGetter = std::move(prettyNameGetter)]() mutable -> void { + nsAutoString prettyExecutableName; + + nsresult result = prettyNameGetter(prettyExecutableName); + + DebugOnly<nsresult> rv = + NS_DispatchToMainThread(NS_NewRunnableFunction( + __func__, + [promiseHolder = std::move(promiseHolder), + prettyExecutableName = std::move(prettyExecutableName), + result]() { + if (NS_FAILED(result)) { + promiseHolder.get()->MaybeReject(result); + } else { + promiseHolder.get()->MaybeResolve(prettyExecutableName); + } + })); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), + "NS_DispatchToMainThread failed"); + }), + NS_DISPATCH_EVENT_MAY_BLOCK); + + if (NS_FAILED(result)) { + promiseHolder.get()->MaybeReject(result); + } + + return NS_OK; +} + NS_IMETHODIMP nsLocalHandlerApp::SetName(const nsAString& aName) { mName.Assign(aName); diff --git a/uriloader/exthandler/nsLocalHandlerApp.h b/uriloader/exthandler/nsLocalHandlerApp.h index 3ea8e3e4fc..ebe43f7dcb 100644 --- a/uriloader/exthandler/nsLocalHandlerApp.h +++ b/uriloader/exthandler/nsLocalHandlerApp.h @@ -12,6 +12,8 @@ #include "nsIFile.h" #include "nsTArray.h" +#include <functional> + class nsLocalHandlerApp : public nsILocalHandlerApp { public: NS_DECL_ISUPPORTS @@ -29,6 +31,9 @@ class nsLocalHandlerApp : public nsILocalHandlerApp { protected: virtual ~nsLocalHandlerApp() {} + virtual std::function<nsresult(nsString&)> + GetPrettyNameOnNonMainThreadCallback(); + nsString mName; nsString mDetailedDescription; nsTArray<nsString> mParameters; @@ -52,6 +57,11 @@ class nsLocalHandlerApp : public nsILocalHandlerApp { # include "mac/nsLocalHandlerAppMac.h" typedef nsLocalHandlerAppMac PlatformLocalHandlerApp_t; # endif +#elif XP_WIN +# ifndef NSLOCALHANDLERAPPWIN_H_ +# include "win/nsLocalHandlerAppWin.h" +typedef nsLocalHandlerAppWin PlatformLocalHandlerApp_t; +# endif #else typedef nsLocalHandlerApp PlatformLocalHandlerApp_t; #endif diff --git a/uriloader/exthandler/nsMIMEInfoImpl.cpp b/uriloader/exthandler/nsMIMEInfoImpl.cpp index 3616ab7fcf..378acb160b 100644 --- a/uriloader/exthandler/nsMIMEInfoImpl.cpp +++ b/uriloader/exthandler/nsMIMEInfoImpl.cpp @@ -231,6 +231,11 @@ nsMIMEInfoBase::GetDefaultDescription(nsAString& aDefaultDescription) { } NS_IMETHODIMP +nsMIMEInfoBase::GetDefaultExecutable(nsIFile** aExecutable) { + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsMIMEInfoBase::GetPreferredApplicationHandler( nsIHandlerApp** aPreferredAppHandler) { *aPreferredAppHandler = mPreferredApplication; @@ -483,6 +488,16 @@ nsMIMEInfoImpl::GetDefaultDescription(nsAString& aDefaultDescription) { return NS_OK; } +NS_IMETHODIMP nsMIMEInfoImpl::GetDefaultExecutable(nsIFile** aExecutable) { + nsCOMPtr<nsIFile> defaultApp = GetDefaultApplication(); + if (defaultApp) { + defaultApp.forget(aExecutable); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP nsMIMEInfoImpl::GetHasDefaultHandler(bool* _retval) { *_retval = !mDefaultAppDescription.IsEmpty(); diff --git a/uriloader/exthandler/nsMIMEInfoImpl.h b/uriloader/exthandler/nsMIMEInfoImpl.h index 9b080ac545..d04566b92c 100644 --- a/uriloader/exthandler/nsMIMEInfoImpl.h +++ b/uriloader/exthandler/nsMIMEInfoImpl.h @@ -57,6 +57,7 @@ class nsMIMEInfoBase : public nsIMIMEInfo { NS_IMETHOD GetPossibleApplicationHandlers( nsIMutableArray** aPossibleAppHandlers) override; NS_IMETHOD GetDefaultDescription(nsAString& aDefaultDescription) override; + NS_IMETHOD GetDefaultExecutable(nsIFile** aExecutable) override; NS_IMETHOD LaunchWithFile(nsIFile* aFile) override; NS_IMETHOD LaunchWithURI( nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) override; @@ -187,6 +188,7 @@ class nsMIMEInfoImpl : public nsMIMEInfoBase { // nsIMIMEInfo methods NS_IMETHOD GetHasDefaultHandler(bool* _retval) override; NS_IMETHOD GetDefaultDescription(nsAString& aDefaultDescription) override; + NS_IMETHOD GetDefaultExecutable(nsIFile** aExecutable) override; NS_IMETHOD IsCurrentAppOSDefault(bool* _retval) override; // additional methods diff --git a/uriloader/exthandler/tests/unit/test_getFromTypeAndExtension.js b/uriloader/exthandler/tests/unit/test_getFromTypeAndExtension.js index 6f4fe52a49..87a013812b 100644 --- a/uriloader/exthandler/tests/unit/test_getFromTypeAndExtension.js +++ b/uriloader/exthandler/tests/unit/test_getFromTypeAndExtension.js @@ -15,3 +15,125 @@ add_task(async function test_utf8_extension() { Assert.equal(someMIME.primaryExtension, ".ัะตัั"); } }); + +function getLocalHandlers(mimeInfo) { + try { + const appList = mimeInfo?.possibleLocalHandlers || []; + return appList; + } catch (err) { + // if the mime info on this platform doesn't support getting local handlers, + // we don't need to test + if (err.result == Cr.NS_ERROR_NOT_IMPLEMENTED) { + return []; + } + + // otherwise, throw the err because the test is broken + throw err; + } +} + +add_task(async function test_default_executable() { + if (AppConstants.platform == "linux") { + return; + } + + const mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService); + let mimeInfo = mimeService.getFromTypeAndExtension("text/html", "html"); + if (mimeInfo !== undefined) { + if (mimeInfo.hasDefaultHandler) { + let defaultExecutableFile = mimeInfo.defaultExecutable; + if (defaultExecutableFile) { + if (AppConstants.platform == "win") { + Assert.ok( + defaultExecutableFile.leafName.endsWith(".exe"), + "Default browser on Windows should end with .exe" + ); + } + } + + let foundDefaultInList = false; + + let appList = getLocalHandlers(mimeInfo); + if (!appList.length) { + return; + } + + for (let index = 0; index < appList.length; index++) { + let app = appList.queryElementAt(index, Ci.nsILocalHandlerApp); + let executablePath = app.executable.path; + + if (executablePath == defaultExecutableFile.path) { + foundDefaultInList = true; + break; + } + } + + Assert.ok( + foundDefaultInList, + "The default browser must be returned in the list of executables from the mime info" + ); + } else { + Assert.throws( + () => mimeInfo.defaultExecutable, + /NS_ERROR_FAILURE/, + "Fetching the defaultExecutable should generate an exception; this line should never be reached" + ); + } + } +}); + +add_task(async function test_pretty_name_for_edge() { + if (AppConstants.platform == "win" && !AppConstants.IS_ESR) { + const mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService); + + let mimeInfo = mimeService.getFromTypeAndExtension("text/html", "html"); + let appList = getLocalHandlers(mimeInfo); + for (let index = 0; index < appList.length; index++) { + let app = appList.queryElementAt(index, Ci.nsILocalHandlerApp); + if (app) { + let executableName = app.executable?.displayName; + if (executableName) { + let prettyName = await app.prettyNameAsync(); + + // Hardcode Edge, as an extra test, when it's installed + if (executableName == "msedge.exe") { + Assert.equal( + prettyName, + "Microsoft Edge", + "The generated pretty name for MS Edge should match the expectation." + ); + } + + // The pretty name should always be something nicer than the executable name. + // This isn't testing that's nice, but should be good enough to validate that + // something other than the executable is found. + Assert.notEqual(executableName, prettyName); + } + } + } + } +}); + +add_task(async function test_pretty_names_match_names_on_non_windows() { + if (AppConstants.platform != "win") { + const mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService); + + let mimeInfo = mimeService.getFromTypeAndExtension("text/html", "html"); + let appList = getLocalHandlers(mimeInfo); + for (let index = 0; index < appList.length; index++) { + let app = appList.queryElementAt(index, Ci.nsILocalHandlerApp); + if (app) { + if (app.executable) { + let name = app.executable.name; + let prettyName = await app.prettyNameAsync(); + + Assert.equal( + prettyName, + name, + "On platforms other than windows, the prettyName and the name of file handlers should be the same." + ); + } + } + } + } +}); diff --git a/uriloader/exthandler/tests/unit/xpcshell.toml b/uriloader/exthandler/tests/unit/xpcshell.toml index 216ad49555..91e1f65e48 100644 --- a/uriloader/exthandler/tests/unit/xpcshell.toml +++ b/uriloader/exthandler/tests/unit/xpcshell.toml @@ -18,6 +18,7 @@ skip-if = [ skip-if = ["os == 'mac'"] # Bug 1817727 ["test_getFromTypeAndExtension.js"] +skip-if = ["os == 'android'"] ["test_getMIMEInfo_pdf.js"] diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp index 330c441159..038ba672d9 100644 --- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp +++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp @@ -9,6 +9,8 @@ #include "nsIGIOService.h" #include "nsNetCID.h" #include "nsIIOService.h" +#include "nsLocalFile.h" + #ifdef MOZ_ENABLE_DBUS # include "nsDBusHandlerApp.h" #endif @@ -17,6 +19,17 @@ nsresult nsMIMEInfoUnix::LoadUriInternal(nsIURI* aURI) { return nsGNOMERegistry::LoadURL(aURI); } +NS_IMETHODIMP nsMIMEInfoUnix::GetDefaultExecutable(nsIFile** aExecutable) { + // This needs to be implemented before FirefoxBridge will work on Linux. + // To implement this and be consistent, GetHasDefaultHandler and + // LaunchDefaultWithFile should probably be made to be consistent. + // Right now, they aren't. GetHasDefaultHandler reports true in cases + // where calling LaunchDefaultWithFile will fail due to not finding the + // right executable. + + return NS_ERROR_NOT_IMPLEMENTED; +} + NS_IMETHODIMP nsMIMEInfoUnix::GetHasDefaultHandler(bool* _retval) { // if a default app is set, it means the application has been set from diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.h b/uriloader/exthandler/unix/nsMIMEInfoUnix.h index 2e32be4915..0d2ca67c07 100644 --- a/uriloader/exthandler/unix/nsMIMEInfoUnix.h +++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.h @@ -20,6 +20,7 @@ class nsMIMEInfoUnix : public nsMIMEInfoImpl { static bool HandlerExists(const char* aProtocolScheme); protected: + NS_IMETHOD GetDefaultExecutable(nsIFile** aExecutable) override; NS_IMETHOD GetHasDefaultHandler(bool* _retval) override; virtual nsresult LoadUriInternal(nsIURI* aURI) override; diff --git a/uriloader/exthandler/win/nsLocalHandlerAppWin.cpp b/uriloader/exthandler/win/nsLocalHandlerAppWin.cpp new file mode 100644 index 0000000000..df5cfbee03 --- /dev/null +++ b/uriloader/exthandler/win/nsLocalHandlerAppWin.cpp @@ -0,0 +1,119 @@ +/* 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<nsILocalFileWin>& 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<nsIWindowsRegKey>& 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<nsresult(nsString&)> +nsLocalHandlerAppWin::GetPrettyNameOnNonMainThreadCallback() { + // Make a copy of executable so that we don't have to worry about any other + // threads + nsCOMPtr<nsIFile> executable; + mExecutable->Clone(getter_AddRefs(executable)); + + // Get the windows interface to the file + nsCOMPtr<nsILocalFileWin> executableOnWindows(do_QueryInterface(executable)); + auto appIdOrName = mAppIdOrName; + auto assignedName = mName; + + std::function<nsresult(nsString&)> 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<nsIWindowsRegKey> 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; +} diff --git a/uriloader/exthandler/win/nsLocalHandlerAppWin.h b/uriloader/exthandler/win/nsLocalHandlerAppWin.h new file mode 100644 index 0000000000..68deda05f4 --- /dev/null +++ b/uriloader/exthandler/win/nsLocalHandlerAppWin.h @@ -0,0 +1,34 @@ +/* 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/. */ + +#ifndef NSLOCALHANDLERAPPWIN_H_ +#define NSLOCALHANDLERAPPWIN_H_ + +#include "nsLocalHandlerApp.h" +#include "nsString.h" + +class nsLocalHandlerAppWin : public nsLocalHandlerApp { + public: + nsLocalHandlerAppWin() {} + + nsLocalHandlerAppWin(const char16_t* aName, nsIFile* aExecutable) + : nsLocalHandlerApp(aName, aExecutable) {} + + nsLocalHandlerAppWin(const nsAString& aName, nsIFile* aExecutable) + : nsLocalHandlerApp(aName, aExecutable) {} + virtual ~nsLocalHandlerAppWin() {} + + void SetAppIdOrName(const nsString& appIdOrName) { + mAppIdOrName = appIdOrName; + } + + protected: + std::function<nsresult(nsString&)> GetPrettyNameOnNonMainThreadCallback() + override; + + private: + nsString mAppIdOrName; +}; + +#endif /*NSLOCALHANDLERAPPMAC_H_*/ diff --git a/uriloader/exthandler/win/nsMIMEInfoWin.cpp b/uriloader/exthandler/win/nsMIMEInfoWin.cpp index 758b2018a7..24044c5f25 100644 --- a/uriloader/exthandler/win/nsMIMEInfoWin.cpp +++ b/uriloader/exthandler/win/nsMIMEInfoWin.cpp @@ -9,6 +9,7 @@ #include "nsCOMArray.h" #include "nsLocalFile.h" #include "nsMIMEInfoWin.h" +#include "nsLocalHandlerAppWin.h" #include "nsIMIMEService.h" #include "nsNetUtil.h" #include <windows.h> @@ -221,6 +222,16 @@ nsMIMEInfoWin::GetHasDefaultHandler(bool* _retval) { return NS_OK; } +NS_IMETHODIMP nsMIMEInfoWin::GetDefaultExecutable(nsIFile** aExecutable) { + nsCOMPtr<nsIFile> defaultApp = GetDefaultApplication(); + if (defaultApp) { + defaultApp.forget(aExecutable); + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP nsMIMEInfoWin::GetEnumerator(nsISimpleEnumerator** _retval) { nsCOMArray<nsIVariant> properties; @@ -554,6 +565,7 @@ bool nsMIMEInfoWin::GetProgIDVerbCommandHandler(const nsAString& appProgIDName, // entries to lower case and stores them in the trackList array. void nsMIMEInfoWin::ProcessPath(nsCOMPtr<nsIMutableArray>& appList, nsTArray<nsString>& trackList, + const nsAutoString& appIdOrName, const nsAString& appFilesystemCommand) { nsAutoString lower(appFilesystemCommand); ToLowerCase(lower); @@ -569,6 +581,9 @@ void nsMIMEInfoWin::ProcessPath(nsCOMPtr<nsIMutableArray>& appList, nsCOMPtr<nsILocalHandlerApp> aApp; if (!GetLocalHandlerApp(appFilesystemCommand, aApp)) return; + // Track the app id so that the pretty name can be determined later + (static_cast<nsLocalHandlerAppWin*>(aApp.get()))->SetAppIdOrName(appIdOrName); + // Save in our main tracking arrays appList->AppendElement(aApp); trackList.AppendElement(lower); @@ -673,7 +688,7 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray** _retval) { if (GetProgIDVerbCommandHandler(appProgId, appFilesystemCommand, false) && !IsPathInList(appFilesystemCommand, trackList)) { - ProcessPath(appList, trackList, appFilesystemCommand); + ProcessPath(appList, trackList, appProgId, appFilesystemCommand); } } } @@ -701,7 +716,7 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray** _retval) { false) || IsPathInList(appFilesystemCommand, trackList)) continue; - ProcessPath(appList, trackList, appFilesystemCommand); + ProcessPath(appList, trackList, appName, appFilesystemCommand); } } regKey->Close(); @@ -729,7 +744,7 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray** _retval) { false) || IsPathInList(appFilesystemCommand, trackList)) continue; - ProcessPath(appList, trackList, appFilesystemCommand); + ProcessPath(appList, trackList, appProgId, appFilesystemCommand); } } regKey->Close(); @@ -762,7 +777,7 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray** _retval) { false) || IsPathInList(appFilesystemCommand, trackList)) continue; - ProcessPath(appList, trackList, appFilesystemCommand); + ProcessPath(appList, trackList, appValue, appFilesystemCommand); } } } @@ -791,7 +806,7 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray** _retval) { false) || IsPathInList(appFilesystemCommand, trackList)) continue; - ProcessPath(appList, trackList, appFilesystemCommand); + ProcessPath(appList, trackList, appProgId, appFilesystemCommand); } } regKey->Close(); @@ -829,7 +844,7 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray** _retval) { false) || IsPathInList(appFilesystemCommand, trackList)) continue; - ProcessPath(appList, trackList, appFilesystemCommand); + ProcessPath(appList, trackList, appName, appFilesystemCommand); } } } @@ -857,7 +872,7 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray** _retval) { if (!GetAppsVerbCommandHandler(appName, appFilesystemCommand, false) || IsPathInList(appFilesystemCommand, trackList)) continue; - ProcessPath(appList, trackList, appFilesystemCommand); + ProcessPath(appList, trackList, appName, appFilesystemCommand); } } regKey->Close(); @@ -882,7 +897,7 @@ nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray** _retval) { if (!GetAppsVerbCommandHandler(appName, appFilesystemCommand, false) || IsPathInList(appFilesystemCommand, trackList)) continue; - ProcessPath(appList, trackList, appFilesystemCommand); + ProcessPath(appList, trackList, appName, appFilesystemCommand); } } } diff --git a/uriloader/exthandler/win/nsMIMEInfoWin.h b/uriloader/exthandler/win/nsMIMEInfoWin.h index fa972b23a9..a7bc40c696 100644 --- a/uriloader/exthandler/win/nsMIMEInfoWin.h +++ b/uriloader/exthandler/win/nsMIMEInfoWin.h @@ -22,6 +22,7 @@ class nsMIMEInfoWin : public nsMIMEInfoBase, public nsIPropertyBag { NS_IMETHOD LaunchWithFile(nsIFile* aFile) override; NS_IMETHOD GetHasDefaultHandler(bool* _retval) override; + NS_IMETHOD GetDefaultExecutable(nsIFile** aExecutable) override; NS_IMETHOD GetPossibleLocalHandlers(nsIArray** _retval) override; NS_IMETHOD IsCurrentAppOSDefault(bool* _retval) override; @@ -68,7 +69,7 @@ class nsMIMEInfoWin : public nsMIMEInfoBase, public nsIPropertyBag { // Helper routine used in tracking app lists void ProcessPath(nsCOMPtr<nsIMutableArray>& appList, - nsTArray<nsString>& trackList, + nsTArray<nsString>& trackList, const nsAutoString& appId, const nsAString& appFilesystemCommand); // Helper routine to call mozilla::ShellExecuteByExplorer |