2007-07-26 08:24:25 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
1999-07-03 00:08:27 +04:00
|
|
|
|
|
|
|
#include "nsMIMEInfoImpl.h"
|
2017-08-17 08:29:03 +03:00
|
|
|
#include "nsString.h"
|
2001-09-29 12:28:41 +04:00
|
|
|
#include "nsReadableUtils.h"
|
2003-06-17 21:00:40 +04:00
|
|
|
#include "nsStringEnumerator.h"
|
2012-06-06 06:08:30 +04:00
|
|
|
#include "nsIFile.h"
|
2007-07-18 02:59:58 +04:00
|
|
|
#include "nsIFileURL.h"
|
2007-09-03 08:44:25 +04:00
|
|
|
#include "nsEscape.h"
|
|
|
|
#include "nsCURILoader.h"
|
Bug 1496380 - stop recursion via the external protocol handler if Firefox is either the default OS handler or a configured external handler, r=mossop
This is an initial implementation of this idea that works on mac.
I've added a Windows implementation in another commit in this stack. I'll
look at a Linux one in a follow-up bug. I do not think we need them in the
child process implementation or on Android.
Effectively, this makes nsIHandlerInfo::LaunchWithURI() fall back to asking if
the handler info points to the OS default and that's us, or if it points to
a helper app and that's us. The latter is fairly easy to check, but the former,
more common case, is actually annoying - there don't seem to be APIs on the
external helper app service or the handler service that provide any information
about the app that's currently the default. So despite my belief that these
interfaces have too many methods that all do very similar things, and what we
need is fewer interfaces with fewer methods, I added another one...
For this mac implementation, I'm comparing bundle URLs and added newer API
usage for 10.10 and later to avoid deprecation warnings. I've not changed
the mac shell service as it uses bundle identifiers to check if we're the
default.
Another way of fixing these issues would be to complain about things when we
receive these URIs from external parties and our own config says that we will
just hand them to someone else. I decided not to do so because we end up with
at least one of the following problems:
- if we implement in BrowserContentHandler, that won't help for
PWAs/Thunderbird
- if we try to implement in the external protocol handler, we'd need to start
passing load flag information through to lots of checks.
- it wouldn't stop the recursion until we've already done one round of
it for links that are in webpages, which seems suboptimal (ie, if you
clicked a mailto: link on a webpage it'd go to the OS with that mailto link
and only realize something's awry when we've gone back through the OS to us,
rather than straightaway).
If we wanted to, we could add a fix like that in belt-and-suspenders fashion.
Differential Revision: https://phabricator.services.mozilla.com/D48742
--HG--
extra : moz-landing-system : lando
2019-11-26 21:51:04 +03:00
|
|
|
#include "nsCExternalHandlerService.h"
|
|
|
|
#include "nsIExternalProtocolService.h"
|
|
|
|
#include "mozilla/StaticPtr.h"
|
|
|
|
|
|
|
|
static bool sInitializedOurData = false;
|
|
|
|
StaticRefPtr<nsIFile> sOurAppFile;
|
|
|
|
|
|
|
|
static already_AddRefed<nsIFile> GetCanonicalExecutable(nsIFile* aFile) {
|
|
|
|
nsCOMPtr<nsIFile> binary = aFile;
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
nsAutoString leafName;
|
|
|
|
if (binary) {
|
|
|
|
binary->GetLeafName(leafName);
|
|
|
|
}
|
|
|
|
while (binary && !StringEndsWith(leafName, NS_LITERAL_STRING(".app"))) {
|
|
|
|
nsCOMPtr<nsIFile> parent;
|
|
|
|
binary->GetParent(getter_AddRefs(parent));
|
|
|
|
binary = parent;
|
|
|
|
if (binary) {
|
|
|
|
binary->GetLeafName(leafName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return binary.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void EnsureAppDetailsAvailable() {
|
|
|
|
if (sInitializedOurData) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
sInitializedOurData = true;
|
|
|
|
nsCOMPtr<nsIFile> binary;
|
|
|
|
XRE_GetBinaryPath(getter_AddRefs(binary));
|
|
|
|
sOurAppFile = GetCanonicalExecutable(binary);
|
|
|
|
ClearOnShutdown(&sOurAppFile);
|
|
|
|
}
|
1999-07-03 00:08:27 +04:00
|
|
|
|
|
|
|
// nsISupports methods
|
2013-07-19 06:24:15 +04:00
|
|
|
NS_IMPL_ADDREF(nsMIMEInfoBase)
|
|
|
|
NS_IMPL_RELEASE(nsMIMEInfoBase)
|
2007-07-26 00:40:41 +04:00
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsMIMEInfoBase)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIHandlerInfo)
|
|
|
|
// This is only an nsIMIMEInfo if it's a MIME handler.
|
|
|
|
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIMIMEInfo, mClass == eMIMEInfo)
|
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIHandlerInfo)
|
2018-02-12 22:36:46 +03:00
|
|
|
NS_INTERFACE_MAP_END
|
1999-07-03 00:08:27 +04:00
|
|
|
|
|
|
|
// nsMIMEInfoImpl methods
|
2007-07-26 00:40:41 +04:00
|
|
|
|
|
|
|
// Constructors for a MIME handler.
|
2004-02-24 01:49:28 +03:00
|
|
|
nsMIMEInfoBase::nsMIMEInfoBase(const char* aMIMEType)
|
2010-05-06 11:22:01 +04:00
|
|
|
: mSchemeOrType(aMIMEType),
|
2007-07-26 00:40:41 +04:00
|
|
|
mClass(eMIMEInfo),
|
2004-02-24 01:49:28 +03:00
|
|
|
mPreferredAction(nsIMIMEInfo::saveToDisk),
|
2011-10-17 18:59:28 +04:00
|
|
|
mAlwaysAskBeforeHandling(true) {}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2004-06-11 19:47:57 +04:00
|
|
|
nsMIMEInfoBase::nsMIMEInfoBase(const nsACString& aMIMEType)
|
2010-05-06 11:22:01 +04:00
|
|
|
: mSchemeOrType(aMIMEType),
|
2007-07-26 00:40:41 +04:00
|
|
|
mClass(eMIMEInfo),
|
|
|
|
mPreferredAction(nsIMIMEInfo::saveToDisk),
|
2011-10-17 18:59:28 +04:00
|
|
|
mAlwaysAskBeforeHandling(true) {}
|
2007-07-26 00:40:41 +04:00
|
|
|
|
|
|
|
// Constructor for a handler that lets the caller specify whether this is a
|
|
|
|
// MIME handler or a protocol handler. In the long run, these will be distinct
|
|
|
|
// classes (f.e. nsMIMEInfo and nsProtocolInfo), but for now we reuse this class
|
|
|
|
// for both and distinguish between the two kinds of handlers via the aClass
|
|
|
|
// argument to this method, which can be either eMIMEInfo or eProtocolInfo.
|
|
|
|
nsMIMEInfoBase::nsMIMEInfoBase(const nsACString& aType, HandlerClass aClass)
|
2010-05-06 11:22:01 +04:00
|
|
|
: mSchemeOrType(aType),
|
2007-07-26 00:40:41 +04:00
|
|
|
mClass(aClass),
|
2004-06-11 19:47:57 +04:00
|
|
|
mPreferredAction(nsIMIMEInfo::saveToDisk),
|
2011-10-17 18:59:28 +04:00
|
|
|
mAlwaysAskBeforeHandling(true) {}
|
2004-06-11 19:47:57 +04:00
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
nsMIMEInfoBase::~nsMIMEInfoBase() {}
|
2000-01-25 05:40:16 +03:00
|
|
|
|
2000-01-24 18:41:03 +03:00
|
|
|
NS_IMETHODIMP
|
2004-02-24 01:49:28 +03:00
|
|
|
nsMIMEInfoBase::GetFileExtensions(nsIUTF8StringEnumerator** aResult) {
|
2003-06-17 21:00:40 +04:00
|
|
|
return NS_NewUTF8StringEnumerator(aResult, &mExtensions, this);
|
1999-07-03 00:08:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
nsMIMEInfoBase::ExtensionExists(const nsACString& aExtension, bool* _retval) {
|
2020-02-21 11:30:30 +03:00
|
|
|
MOZ_ASSERT(!aExtension.IsEmpty(), "no extension");
|
|
|
|
*_retval = mExtensions.Contains(aExtension,
|
|
|
|
nsCaseInsensitiveCStringArrayComparator());
|
1999-07-03 00:08:27 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2000-01-24 18:41:03 +03:00
|
|
|
NS_IMETHODIMP
|
2004-04-16 00:56:37 +04:00
|
|
|
nsMIMEInfoBase::GetPrimaryExtension(nsACString& _retval) {
|
2020-02-21 11:30:30 +03:00
|
|
|
if (!mExtensions.Length()) {
|
|
|
|
_retval.Truncate();
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
}
|
2009-01-22 07:15:34 +03:00
|
|
|
_retval = mExtensions[0];
|
2000-01-24 18:41:03 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2002-01-16 07:28:06 +03:00
|
|
|
NS_IMETHODIMP
|
2004-04-16 00:56:37 +04:00
|
|
|
nsMIMEInfoBase::SetPrimaryExtension(const nsACString& aExtension) {
|
2020-02-21 11:30:30 +03:00
|
|
|
if (MOZ_UNLIKELY(aExtension.IsEmpty())) {
|
|
|
|
MOZ_ASSERT(false, "No extension");
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
2020-02-18 02:13:03 +03:00
|
|
|
}
|
2020-02-21 11:30:30 +03:00
|
|
|
int32_t i = mExtensions.IndexOf(aExtension, 0,
|
|
|
|
nsCaseInsensitiveCStringArrayComparator());
|
|
|
|
if (i != -1) {
|
2009-01-22 07:15:34 +03:00
|
|
|
mExtensions.RemoveElementAt(i);
|
2002-01-16 07:28:06 +03:00
|
|
|
}
|
2009-01-22 07:15:34 +03:00
|
|
|
mExtensions.InsertElementAt(0, aExtension);
|
2020-02-20 12:55:52 +03:00
|
|
|
return NS_OK;
|
2020-02-19 19:48:10 +03:00
|
|
|
}
|
|
|
|
|
2020-02-21 11:30:30 +03:00
|
|
|
void nsMIMEInfoBase::AddUniqueExtension(const nsACString& aExtension) {
|
|
|
|
if (!aExtension.IsEmpty() &&
|
|
|
|
!mExtensions.Contains(aExtension,
|
|
|
|
nsCaseInsensitiveCStringArrayComparator())) {
|
|
|
|
mExtensions.AppendElement(aExtension);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2004-04-16 00:56:37 +04:00
|
|
|
nsMIMEInfoBase::AppendExtension(const nsACString& aExtension) {
|
2020-02-21 11:30:30 +03:00
|
|
|
MOZ_ASSERT(!aExtension.IsEmpty(), "No extension");
|
|
|
|
AddUniqueExtension(aExtension);
|
2004-04-16 00:56:37 +04:00
|
|
|
return NS_OK;
|
2000-04-05 07:03:50 +04:00
|
|
|
}
|
|
|
|
|
2007-07-26 00:40:41 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMIMEInfoBase::GetType(nsACString& aType) {
|
|
|
|
if (mSchemeOrType.IsEmpty()) return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
2010-05-06 11:22:01 +04:00
|
|
|
aType = mSchemeOrType;
|
2007-07-26 00:40:41 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-12-12 04:02:26 +03:00
|
|
|
NS_IMETHODIMP
|
2004-04-16 00:56:37 +04:00
|
|
|
nsMIMEInfoBase::GetMIMEType(nsACString& aMIMEType) {
|
2000-07-22 03:52:36 +04:00
|
|
|
if (mSchemeOrType.IsEmpty()) return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
2010-05-06 11:22:01 +04:00
|
|
|
aMIMEType = mSchemeOrType;
|
1999-07-03 00:08:27 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2004-04-16 00:56:37 +04:00
|
|
|
nsMIMEInfoBase::GetDescription(nsAString& aDescription) {
|
|
|
|
aDescription = mDescription;
|
1999-07-03 00:08:27 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2004-04-16 00:56:37 +04:00
|
|
|
nsMIMEInfoBase::SetDescription(const nsAString& aDescription) {
|
|
|
|
mDescription = aDescription;
|
|
|
|
return NS_OK;
|
2000-04-05 07:03:50 +04:00
|
|
|
}
|
|
|
|
|
1999-07-03 00:08:27 +04:00
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
nsMIMEInfoBase::Equals(nsIMIMEInfo* aMIMEInfo, bool* _retval) {
|
2000-01-24 18:41:03 +03:00
|
|
|
if (!aMIMEInfo) return NS_ERROR_NULL_POINTER;
|
|
|
|
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString type;
|
2004-04-16 00:56:37 +04:00
|
|
|
nsresult rv = aMIMEInfo->GetMIMEType(type);
|
2000-01-24 18:41:03 +03:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2010-05-06 11:22:01 +04:00
|
|
|
*_retval = mSchemeOrType.Equals(type);
|
2000-04-05 07:03:50 +04:00
|
|
|
|
2000-01-24 18:41:03 +03:00
|
|
|
return NS_OK;
|
1999-07-03 00:08:27 +04:00
|
|
|
}
|
2000-04-05 07:03:50 +04:00
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2004-04-16 00:56:37 +04:00
|
|
|
nsMIMEInfoBase::SetFileExtensions(const nsACString& aExtensions) {
|
|
|
|
mExtensions.Clear();
|
2020-02-21 11:30:30 +03:00
|
|
|
nsACString::const_iterator start, end;
|
|
|
|
aExtensions.BeginReading(start);
|
|
|
|
aExtensions.EndReading(end);
|
|
|
|
while (start != end) {
|
|
|
|
nsACString::const_iterator cursor = start;
|
|
|
|
mozilla::Unused << FindCharInReadable(',', cursor, end);
|
|
|
|
AddUniqueExtension(Substring(start, cursor));
|
|
|
|
// If a comma was found, skip it for the next search.
|
|
|
|
start = cursor != end ? ++cursor : cursor;
|
2004-04-16 00:56:37 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
2000-04-19 08:45:30 +04:00
|
|
|
}
|
2000-06-21 10:34:43 +04:00
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2004-04-16 00:56:37 +04:00
|
|
|
nsMIMEInfoBase::GetDefaultDescription(nsAString& aDefaultDescription) {
|
|
|
|
aDefaultDescription = mDefaultAppDescription;
|
|
|
|
return NS_OK;
|
2003-01-12 04:14:35 +03:00
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2007-07-05 23:31:44 +04:00
|
|
|
nsMIMEInfoBase::GetPreferredApplicationHandler(
|
|
|
|
nsIHandlerApp** aPreferredAppHandler) {
|
2000-06-21 10:34:43 +04:00
|
|
|
*aPreferredAppHandler = mPreferredApplication;
|
2000-06-22 00:38:52 +04:00
|
|
|
NS_IF_ADDREF(*aPreferredAppHandler);
|
2000-06-21 10:34:43 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2007-07-05 23:31:44 +04:00
|
|
|
nsMIMEInfoBase::SetPreferredApplicationHandler(
|
|
|
|
nsIHandlerApp* aPreferredAppHandler) {
|
2000-06-21 10:34:43 +04:00
|
|
|
mPreferredApplication = aPreferredAppHandler;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-08-14 00:41:34 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMIMEInfoBase::GetPossibleApplicationHandlers(
|
|
|
|
nsIMutableArray** aPossibleAppHandlers) {
|
|
|
|
if (!mPossibleApplications)
|
|
|
|
mPossibleApplications = do_CreateInstance(NS_ARRAY_CONTRACTID);
|
|
|
|
|
|
|
|
if (!mPossibleApplications) return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
|
|
|
|
*aPossibleAppHandlers = mPossibleApplications;
|
|
|
|
NS_IF_ADDREF(*aPossibleAppHandlers);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2007-07-05 23:31:44 +04:00
|
|
|
nsMIMEInfoBase::GetPreferredAction(nsHandlerInfoAction* aPreferredAction) {
|
2004-02-24 01:49:28 +03:00
|
|
|
*aPreferredAction = mPreferredAction;
|
2003-07-08 17:52:46 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2007-07-05 23:31:44 +04:00
|
|
|
nsMIMEInfoBase::SetPreferredAction(nsHandlerInfoAction aPreferredAction) {
|
2004-02-24 01:49:28 +03:00
|
|
|
mPreferredAction = aPreferredAction;
|
2003-01-12 04:14:35 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
nsMIMEInfoBase::GetAlwaysAskBeforeHandling(bool* aAlwaysAsk) {
|
2004-02-24 01:49:28 +03:00
|
|
|
*aAlwaysAsk = mAlwaysAskBeforeHandling;
|
|
|
|
|
2003-01-12 04:14:35 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
nsMIMEInfoBase::SetAlwaysAskBeforeHandling(bool aAlwaysAsk) {
|
2004-02-24 01:49:28 +03:00
|
|
|
mAlwaysAskBeforeHandling = aAlwaysAsk;
|
2000-06-21 10:34:43 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-02-24 01:49:28 +03:00
|
|
|
|
2007-07-18 02:59:58 +04:00
|
|
|
/* static */
|
2012-06-06 06:08:30 +04:00
|
|
|
nsresult nsMIMEInfoBase::GetLocalFileFromURI(nsIURI* aURI, nsIFile** aFile) {
|
2007-07-18 02:59:58 +04:00
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(aURI, &rv);
|
2014-03-17 21:00:17 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2007-07-18 02:59:58 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIFile> file;
|
|
|
|
rv = fileUrl->GetFile(getter_AddRefs(file));
|
2014-03-17 21:00:17 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2007-07-18 02:59:58 +04:00
|
|
|
|
2014-03-17 21:00:17 +04:00
|
|
|
file.forget(aFile);
|
|
|
|
return NS_OK;
|
2007-07-18 02:59:58 +04:00
|
|
|
}
|
|
|
|
|
2007-08-21 04:47:47 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMIMEInfoBase::LaunchWithFile(nsIFile* aFile) {
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// it doesn't make any sense to call this on protocol handlers
|
|
|
|
NS_ASSERTION(mClass == eMIMEInfo,
|
|
|
|
"nsMIMEInfoBase should have mClass == eMIMEInfo");
|
|
|
|
|
|
|
|
if (mPreferredAction == useSystemDefault) {
|
|
|
|
return LaunchDefaultWithFile(aFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mPreferredAction == useHelperApp) {
|
|
|
|
if (!mPreferredApplication) return NS_ERROR_FILE_NOT_FOUND;
|
|
|
|
|
|
|
|
// at the moment, we only know how to hand files off to local handlers
|
|
|
|
nsCOMPtr<nsILocalHandlerApp> localHandler =
|
|
|
|
do_QueryInterface(mPreferredApplication, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFile> executable;
|
|
|
|
rv = localHandler->GetExecutable(getter_AddRefs(executable));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2017-12-15 15:53:51 +03:00
|
|
|
return LaunchWithIProcess(executable, aFile->NativePath());
|
2007-08-21 04:47:47 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
2007-07-18 02:59:58 +04:00
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
NS_IMETHODIMP
|
2020-05-11 16:13:03 +03:00
|
|
|
nsMIMEInfoBase::LaunchWithURI(nsIURI* aURI, BrowsingContext* aBrowsingContext) {
|
2020-04-02 00:20:50 +03:00
|
|
|
// This is only being called with protocol handlers
|
2007-08-21 04:47:47 +04:00
|
|
|
NS_ASSERTION(mClass == eProtocolInfo,
|
|
|
|
"nsMIMEInfoBase should be a protocol handler");
|
|
|
|
|
|
|
|
if (mPreferredAction == useSystemDefault) {
|
Bug 1496380 - stop recursion via the external protocol handler if Firefox is either the default OS handler or a configured external handler, r=mossop
This is an initial implementation of this idea that works on mac.
I've added a Windows implementation in another commit in this stack. I'll
look at a Linux one in a follow-up bug. I do not think we need them in the
child process implementation or on Android.
Effectively, this makes nsIHandlerInfo::LaunchWithURI() fall back to asking if
the handler info points to the OS default and that's us, or if it points to
a helper app and that's us. The latter is fairly easy to check, but the former,
more common case, is actually annoying - there don't seem to be APIs on the
external helper app service or the handler service that provide any information
about the app that's currently the default. So despite my belief that these
interfaces have too many methods that all do very similar things, and what we
need is fewer interfaces with fewer methods, I added another one...
For this mac implementation, I'm comparing bundle URLs and added newer API
usage for 10.10 and later to avoid deprecation warnings. I've not changed
the mac shell service as it uses bundle identifiers to check if we're the
default.
Another way of fixing these issues would be to complain about things when we
receive these URIs from external parties and our own config says that we will
just hand them to someone else. I decided not to do so because we end up with
at least one of the following problems:
- if we implement in BrowserContentHandler, that won't help for
PWAs/Thunderbird
- if we try to implement in the external protocol handler, we'd need to start
passing load flag information through to lots of checks.
- it wouldn't stop the recursion until we've already done one round of
it for links that are in webpages, which seems suboptimal (ie, if you
clicked a mailto: link on a webpage it'd go to the OS with that mailto link
and only realize something's awry when we've gone back through the OS to us,
rather than straightaway).
If we wanted to, we could add a fix like that in belt-and-suspenders fashion.
Differential Revision: https://phabricator.services.mozilla.com/D48742
--HG--
extra : moz-landing-system : lando
2019-11-26 21:51:04 +03:00
|
|
|
// First, ensure we're not accidentally going to call ourselves.
|
|
|
|
// That'd lead to an infinite loop (see bug 215554).
|
|
|
|
nsCOMPtr<nsIExternalProtocolService> extProtService =
|
|
|
|
do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);
|
|
|
|
if (!extProtService) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
nsAutoCString scheme;
|
|
|
|
aURI->GetScheme(scheme);
|
|
|
|
bool isDefault = false;
|
|
|
|
nsresult rv =
|
|
|
|
extProtService->IsCurrentAppOSDefaultForProtocol(scheme, &isDefault);
|
|
|
|
if (NS_SUCCEEDED(rv) && isDefault) {
|
|
|
|
// Lie. This will trip the handler service into showing a dialog asking
|
|
|
|
// what the user wants.
|
|
|
|
return NS_ERROR_FILE_NOT_FOUND;
|
|
|
|
}
|
2007-08-21 04:47:47 +04:00
|
|
|
return LoadUriInternal(aURI);
|
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
if (mPreferredAction == useHelperApp) {
|
|
|
|
if (!mPreferredApplication) return NS_ERROR_FILE_NOT_FOUND;
|
|
|
|
|
Bug 1496380 - stop recursion via the external protocol handler if Firefox is either the default OS handler or a configured external handler, r=mossop
This is an initial implementation of this idea that works on mac.
I've added a Windows implementation in another commit in this stack. I'll
look at a Linux one in a follow-up bug. I do not think we need them in the
child process implementation or on Android.
Effectively, this makes nsIHandlerInfo::LaunchWithURI() fall back to asking if
the handler info points to the OS default and that's us, or if it points to
a helper app and that's us. The latter is fairly easy to check, but the former,
more common case, is actually annoying - there don't seem to be APIs on the
external helper app service or the handler service that provide any information
about the app that's currently the default. So despite my belief that these
interfaces have too many methods that all do very similar things, and what we
need is fewer interfaces with fewer methods, I added another one...
For this mac implementation, I'm comparing bundle URLs and added newer API
usage for 10.10 and later to avoid deprecation warnings. I've not changed
the mac shell service as it uses bundle identifiers to check if we're the
default.
Another way of fixing these issues would be to complain about things when we
receive these URIs from external parties and our own config says that we will
just hand them to someone else. I decided not to do so because we end up with
at least one of the following problems:
- if we implement in BrowserContentHandler, that won't help for
PWAs/Thunderbird
- if we try to implement in the external protocol handler, we'd need to start
passing load flag information through to lots of checks.
- it wouldn't stop the recursion until we've already done one round of
it for links that are in webpages, which seems suboptimal (ie, if you
clicked a mailto: link on a webpage it'd go to the OS with that mailto link
and only realize something's awry when we've gone back through the OS to us,
rather than straightaway).
If we wanted to, we could add a fix like that in belt-and-suspenders fashion.
Differential Revision: https://phabricator.services.mozilla.com/D48742
--HG--
extra : moz-landing-system : lando
2019-11-26 21:51:04 +03:00
|
|
|
EnsureAppDetailsAvailable();
|
|
|
|
nsCOMPtr<nsILocalHandlerApp> localPreferredHandler =
|
|
|
|
do_QueryInterface(mPreferredApplication);
|
|
|
|
if (localPreferredHandler) {
|
|
|
|
nsCOMPtr<nsIFile> executable;
|
|
|
|
localPreferredHandler->GetExecutable(getter_AddRefs(executable));
|
|
|
|
executable = GetCanonicalExecutable(executable);
|
|
|
|
bool isOurExecutable = false;
|
|
|
|
if (!executable ||
|
|
|
|
NS_FAILED(executable->Equals(sOurAppFile, &isOurExecutable)) ||
|
|
|
|
isOurExecutable) {
|
|
|
|
// Lie. This will trip the handler service into showing a dialog asking
|
|
|
|
// what the user wants.
|
|
|
|
return NS_ERROR_FILE_NOT_FOUND;
|
|
|
|
}
|
|
|
|
}
|
2020-05-11 16:13:03 +03:00
|
|
|
return mPreferredApplication->LaunchWithURI(aURI, aBrowsingContext);
|
2007-08-21 04:47:47 +04:00
|
|
|
}
|
2004-02-24 01:49:28 +03:00
|
|
|
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
2000-06-21 10:34:43 +04:00
|
|
|
}
|
2000-07-12 03:11:59 +04:00
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
void nsMIMEInfoBase::CopyBasicDataTo(nsMIMEInfoBase* aOther) {
|
2010-05-06 11:22:01 +04:00
|
|
|
aOther->mSchemeOrType = mSchemeOrType;
|
2004-02-24 01:49:28 +03:00
|
|
|
aOther->mDefaultAppDescription = mDefaultAppDescription;
|
2020-04-30 12:38:40 +03:00
|
|
|
aOther->mExtensions = mExtensions.Clone();
|
2000-07-12 03:11:59 +04:00
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
/* static */
|
2010-03-18 11:37:12 +03:00
|
|
|
already_AddRefed<nsIProcess> nsMIMEInfoBase::InitProcess(nsIFile* aApp,
|
|
|
|
nsresult* aResult) {
|
2007-07-29 07:38:52 +04:00
|
|
|
NS_ASSERTION(aApp, "Unexpected null pointer, fix caller");
|
2004-02-24 01:49:28 +03:00
|
|
|
|
2010-03-18 11:37:12 +03:00
|
|
|
nsCOMPtr<nsIProcess> process =
|
|
|
|
do_CreateInstance(NS_PROCESS_CONTRACTID, aResult);
|
|
|
|
if (NS_FAILED(*aResult)) return nullptr;
|
|
|
|
|
2010-07-03 00:56:09 +04:00
|
|
|
*aResult = process->Init(aApp);
|
|
|
|
if (NS_FAILED(*aResult)) return nullptr;
|
2010-03-18 11:37:12 +03:00
|
|
|
|
|
|
|
return process.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
nsresult nsMIMEInfoBase::LaunchWithIProcess(nsIFile* aApp,
|
|
|
|
const nsCString& aArg) {
|
2004-02-24 01:49:28 +03:00
|
|
|
nsresult rv;
|
2010-03-18 11:37:12 +03:00
|
|
|
nsCOMPtr<nsIProcess> process = InitProcess(aApp, &rv);
|
2004-02-24 01:49:28 +03:00
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2007-07-29 07:38:52 +04:00
|
|
|
const char* string = aArg.get();
|
2004-02-24 01:49:28 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return process->Run(false, &string, 1);
|
2004-02-24 01:49:28 +03:00
|
|
|
}
|
|
|
|
|
2010-03-18 11:37:12 +03:00
|
|
|
/* static */
|
|
|
|
nsresult nsMIMEInfoBase::LaunchWithIProcess(nsIFile* aApp,
|
|
|
|
const nsString& aArg) {
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIProcess> process = InitProcess(aApp, &rv);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t* string = aArg.get();
|
2010-03-18 11:37:12 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return process->Runw(false, &string, 1);
|
2010-03-18 11:37:12 +03:00
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
// nsMIMEInfoImpl implementation
|
|
|
|
NS_IMETHODIMP
|
2004-04-16 00:56:37 +04:00
|
|
|
nsMIMEInfoImpl::GetDefaultDescription(nsAString& aDefaultDescription) {
|
2004-02-24 01:49:28 +03:00
|
|
|
if (mDefaultAppDescription.IsEmpty() && mDefaultApplication) {
|
|
|
|
// Don't want to cache this, just in case someone resets the app
|
|
|
|
// without changing the description....
|
2004-04-16 00:56:37 +04:00
|
|
|
mDefaultApplication->GetLeafName(aDefaultDescription);
|
2004-02-24 01:49:28 +03:00
|
|
|
} else {
|
2004-04-16 00:56:37 +04:00
|
|
|
aDefaultDescription = mDefaultAppDescription;
|
2004-02-24 01:49:28 +03:00
|
|
|
}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2004-04-16 00:56:37 +04:00
|
|
|
return NS_OK;
|
2004-02-24 01:49:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
nsMIMEInfoImpl::GetHasDefaultHandler(bool* _retval) {
|
2007-07-31 03:33:16 +04:00
|
|
|
*_retval = !mDefaultAppDescription.IsEmpty();
|
2004-02-24 01:49:28 +03:00
|
|
|
if (mDefaultApplication) {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool exists;
|
2004-02-24 01:49:28 +03:00
|
|
|
*_retval = NS_SUCCEEDED(mDefaultApplication->Exists(&exists)) && exists;
|
|
|
|
}
|
2000-07-12 03:11:59 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2004-02-24 01:49:28 +03:00
|
|
|
|
2020-05-06 23:25:29 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMIMEInfoImpl::IsCurrentAppOSDefault(bool* _retval) {
|
|
|
|
*_retval = false;
|
|
|
|
if (mDefaultApplication) {
|
|
|
|
// Determine if the default executable is our executable.
|
|
|
|
EnsureAppDetailsAvailable();
|
|
|
|
bool isSame = false;
|
|
|
|
nsresult rv = mDefaultApplication->Equals(sOurAppFile, &isSame);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
*_retval = isSame;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-02-24 01:49:28 +03:00
|
|
|
nsresult nsMIMEInfoImpl::LaunchDefaultWithFile(nsIFile* aFile) {
|
|
|
|
if (!mDefaultApplication) return NS_ERROR_FILE_NOT_FOUND;
|
|
|
|
|
2017-12-15 15:53:51 +03:00
|
|
|
return LaunchWithIProcess(mDefaultApplication, aFile->NativePath());
|
2004-02-24 01:49:28 +03:00
|
|
|
}
|
|
|
|
|
2007-10-19 08:15:41 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsMIMEInfoBase::GetPossibleLocalHandlers(nsIArray** _retval) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|