Bug 1884785 - Expose the path to the os default application to privileged extensions r=Gijs,necko-reviewers

Added in some code to expose the path to the os default application. Tested via tests on Windows. Mac and Linux will use the nsMIMEInfoImpl which will supply the functionality for them and be tested with the auto-tests.

Differential Revision: https://phabricator.services.mozilla.com/D204306
This commit is contained in:
Michael Hughes 2024-03-25 23:19:17 +00:00
Родитель e66ab7ac30
Коммит 64fe1d816e
10 изменённых файлов: 126 добавлений и 32 удалений

Просмотреть файл

@ -53,18 +53,23 @@ interface nsIHandlerInfo : nsISupports {
readonly attribute nsIMutableArray possibleApplicationHandlers;
/**
* Indicates whether a default application handler exists,
* Indicates whether a default OS application handler exists,
* i.e. whether launchWithFile with action = useSystemDefault is possible
* and defaultDescription will contain usable information.
*/
readonly attribute boolean hasDefaultHandler;
/**
* A pretty name description of the associated default application. Only
* A pretty name description of the associated default OS application. Only
* usable if hasDefaultHandler is true.
*/
readonly attribute AString defaultDescription;
/**
* The default OS application. Only usable if hasDefaultHandler is true.
*/
readonly attribute nsIFile defaultExecutable;
/**
* Launches the application with the specified URI, in a way that
* depends on the value of preferredAction. preferredAction must be

Просмотреть файл

@ -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(

Просмотреть файл

@ -124,6 +124,11 @@ nsMIMEInfoAndroid::GetDefaultDescription(nsAString& aDesc) {
return NS_OK;
}
NS_IMETHODIMP
nsMIMEInfoAndroid::GetDefaultExecutable(nsIFile** aExecutable) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMIMEInfoAndroid::LaunchWithURI(
nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) {

Просмотреть файл

@ -230,6 +230,11 @@ nsMIMEInfoBase::GetDefaultDescription(nsAString& aDefaultDescription) {
return NS_OK;
}
NS_IMETHODIMP
nsMIMEInfoBase::GetDefaultExecutable(nsIFile** aExecutable) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMIMEInfoBase::GetPreferredApplicationHandler(
nsIHandlerApp** aPreferredAppHandler) {
@ -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();

Просмотреть файл

@ -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

Просмотреть файл

@ -16,26 +16,78 @@ add_task(async function test_utf8_extension() {
}
});
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 = [];
try {
appList = mimeInfo?.possibleLocalHandlers || [];
} 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;
}
let appList = getLocalHandlers(mimeInfo);
for (let index = 0; index < appList.length; index++) {
let app = appList.queryElementAt(index, Ci.nsILocalHandlerApp);
if (app) {
@ -67,21 +119,7 @@ add_task(async function test_pretty_names_match_names_on_non_windows() {
const mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let mimeInfo = mimeService.getFromTypeAndExtension("text/html", "html");
let appList = [];
try {
appList = mimeInfo?.possibleLocalHandlers || [];
} 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;
}
let appList = getLocalHandlers(mimeInfo);
for (let index = 0; index < appList.length; index++) {
let app = appList.queryElementAt(index, Ci.nsILocalHandlerApp);
if (app) {

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -222,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;

Просмотреть файл

@ -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;