forked from mirrors/gecko-dev
The mIsTrackingResource flag on nsIHttpChannel was split into two separate flags depending on whether or not the resource is third-party. The correct flag will be set by the channel classifier. Similarly, a new function was introduced, GetIsThirdPartyTrackingResource(), for those consumers (like TP) who only care about third-party trackers. The existing function, GetIsTracking(), will continue to look at both first-party and third-party trackers (the behavior since first party tracking was added to annotations in bug 1476324). The OverrideTrackingResource() function now allows nsHTMLDocument to override both mIsFirstPartyTrackingResource and mIsThirdPartyTrackingResource, but since this function is a little dangerous and only has a single user, I added an assert to make future callers think twice about using it to opt out of tracking annotations. Currently, only the default storage restrictions need to look at first-party trackers so every other consumer has been moved to mIsThirdPartyTrackingResource or GetIsThirdPartyTrackingResource(). This effectively reverts the third-party checks added in bug 1476715 and replaces them with the more complicated check that was added in bug 1108017. It follows the approach that Ehsan initially suggested in bug 1476715. It also reverts the changes in the expected values of the tracking annotation test since these were, in hindsight, a warning about this regression. Depends on D3722 Differential Revision: https://phabricator.services.mozilla.com/D3723 --HG-- extra : moz-landing-system : lando
589 lines
17 KiB
C++
589 lines
17 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
* vim:set ts=2 sts=2 sw=2 et cin:
|
|
*
|
|
* 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 "nsIURI.h"
|
|
#include "nsIURL.h"
|
|
#include "nsExternalProtocolHandler.h"
|
|
#include "nsString.h"
|
|
#include "nsReadableUtils.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsServiceManagerUtils.h"
|
|
#include "nsIInterfaceRequestor.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "nsIStringBundle.h"
|
|
#include "nsIPrefService.h"
|
|
#include "nsIPrompt.h"
|
|
#include "nsIURIMutator.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsContentSecurityManager.h"
|
|
#include "nsExternalHelperAppService.h"
|
|
|
|
// used to dispatch urls to default protocol handlers
|
|
#include "nsCExternalHandlerService.h"
|
|
#include "nsIExternalProtocolService.h"
|
|
#include "nsIChildChannel.h"
|
|
#include "nsIParentChannel.h"
|
|
|
|
class nsILoadInfo;
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// a stub channel implemenation which will map calls to AsyncRead and OpenInputStream
|
|
// to calls in the OS for loading the url.
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
class nsExtProtocolChannel : public nsIChannel,
|
|
public nsIChildChannel,
|
|
public nsIParentChannel
|
|
{
|
|
public:
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
NS_DECL_NSICHANNEL
|
|
NS_DECL_NSIREQUESTOBSERVER
|
|
NS_DECL_NSISTREAMLISTENER
|
|
NS_DECL_NSIREQUEST
|
|
NS_DECL_NSICHILDCHANNEL
|
|
NS_DECL_NSIPARENTCHANNEL
|
|
|
|
nsExtProtocolChannel(nsIURI* aURI, nsILoadInfo* aLoadInfo);
|
|
|
|
private:
|
|
virtual ~nsExtProtocolChannel();
|
|
|
|
nsresult OpenURL();
|
|
void Finish(nsresult aResult);
|
|
|
|
nsCOMPtr<nsIURI> mUrl;
|
|
nsCOMPtr<nsIURI> mOriginalURI;
|
|
nsresult mStatus;
|
|
nsLoadFlags mLoadFlags;
|
|
bool mWasOpened;
|
|
// Set true (as a result of ConnectParent invoked from child process)
|
|
// when this channel is on the parent process and is being used as
|
|
// a redirect target channel. It turns AsyncOpen into a no-op since
|
|
// we do it on the child.
|
|
bool mConnectedParent;
|
|
|
|
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
|
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
|
nsCOMPtr<nsILoadInfo> mLoadInfo;
|
|
nsCOMPtr<nsIStreamListener> mListener;
|
|
};
|
|
|
|
NS_IMPL_ADDREF(nsExtProtocolChannel)
|
|
NS_IMPL_RELEASE(nsExtProtocolChannel)
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsExtProtocolChannel)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChannel)
|
|
NS_INTERFACE_MAP_ENTRY(nsIChannel)
|
|
NS_INTERFACE_MAP_ENTRY(nsIRequest)
|
|
NS_INTERFACE_MAP_ENTRY(nsIChildChannel)
|
|
NS_INTERFACE_MAP_ENTRY(nsIParentChannel)
|
|
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
|
|
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
nsExtProtocolChannel::nsExtProtocolChannel(nsIURI* aURI,
|
|
nsILoadInfo* aLoadInfo)
|
|
: mUrl(aURI)
|
|
, mOriginalURI(aURI)
|
|
, mStatus(NS_OK)
|
|
, mLoadFlags(nsIRequest::LOAD_NORMAL)
|
|
, mWasOpened(false)
|
|
, mConnectedParent(false)
|
|
, mLoadInfo(aLoadInfo)
|
|
{
|
|
}
|
|
|
|
nsExtProtocolChannel::~nsExtProtocolChannel()
|
|
{}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
|
|
{
|
|
NS_IF_ADDREF(*aLoadGroup = mLoadGroup);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
|
|
{
|
|
mLoadGroup = aLoadGroup;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
|
|
{
|
|
NS_IF_ADDREF(*aCallbacks = mCallbacks);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
|
|
{
|
|
mCallbacks = aCallbacks;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsExtProtocolChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
|
|
{
|
|
*aSecurityInfo = nullptr;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetOriginalURI(nsIURI* *aURI)
|
|
{
|
|
NS_ADDREF(*aURI = mOriginalURI);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetOriginalURI(nsIURI* aURI)
|
|
{
|
|
NS_ENSURE_ARG_POINTER(aURI);
|
|
mOriginalURI = aURI;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetURI(nsIURI* *aURI)
|
|
{
|
|
*aURI = mUrl;
|
|
NS_IF_ADDREF(*aURI);
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult nsExtProtocolChannel::OpenURL()
|
|
{
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
nsCOMPtr<nsIExternalProtocolService> extProtService (do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
|
|
|
|
if (extProtService)
|
|
{
|
|
#ifdef DEBUG
|
|
nsAutoCString urlScheme;
|
|
mUrl->GetScheme(urlScheme);
|
|
bool haveHandler = false;
|
|
extProtService->ExternalProtocolHandlerExists(urlScheme.get(), &haveHandler);
|
|
NS_ASSERTION(haveHandler, "Why do we have a channel for this url if we don't support the protocol?");
|
|
#endif
|
|
|
|
nsCOMPtr<nsIInterfaceRequestor> aggCallbacks;
|
|
rv = NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
|
|
getter_AddRefs(aggCallbacks));
|
|
if (NS_FAILED(rv)) {
|
|
goto finish;
|
|
}
|
|
|
|
rv = extProtService->LoadURI(mUrl, aggCallbacks);
|
|
|
|
if (NS_SUCCEEDED(rv) && mListener) {
|
|
Cancel(NS_ERROR_NO_CONTENT);
|
|
|
|
RefPtr<nsExtProtocolChannel> self = this;
|
|
nsCOMPtr<nsIStreamListener> listener = mListener;
|
|
MessageLoop::current()->PostTask(
|
|
NS_NewRunnableFunction(
|
|
"nsExtProtocolChannel::OpenURL",
|
|
[self, listener]() {
|
|
listener->OnStartRequest(self, nullptr);
|
|
listener->OnStopRequest(self, nullptr, self->mStatus);
|
|
}));
|
|
}
|
|
}
|
|
|
|
finish:
|
|
mCallbacks = nullptr;
|
|
mListener = nullptr;
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::Open(nsIInputStream **_retval)
|
|
{
|
|
return OpenURL();
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::Open2(nsIInputStream** aStream)
|
|
{
|
|
nsCOMPtr<nsIStreamListener> listener;
|
|
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
return Open(aStream);
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
|
|
{
|
|
if (mConnectedParent) {
|
|
return NS_OK;
|
|
}
|
|
|
|
MOZ_ASSERT(!mLoadInfo ||
|
|
mLoadInfo->GetSecurityMode() == 0 ||
|
|
mLoadInfo->GetInitialSecurityCheckDone() ||
|
|
(mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
|
|
nsContentUtils::IsSystemPrincipal(mLoadInfo->LoadingPrincipal())),
|
|
"security flags in loadInfo but asyncOpen2() not called");
|
|
|
|
NS_ENSURE_ARG_POINTER(listener);
|
|
NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED);
|
|
|
|
mWasOpened = true;
|
|
mListener = listener;
|
|
|
|
return OpenURL();
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::AsyncOpen2(nsIStreamListener *aListener)
|
|
{
|
|
nsCOMPtr<nsIStreamListener> listener = aListener;
|
|
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
|
if (NS_FAILED(rv)) {
|
|
mCallbacks = nullptr;
|
|
return rv;
|
|
}
|
|
return AsyncOpen(listener, nullptr);
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
|
|
{
|
|
*aLoadFlags = mLoadFlags;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
|
|
{
|
|
mLoadFlags = aLoadFlags;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetIsDocument(bool *aIsDocument)
|
|
{
|
|
return NS_GetIsDocumentChannel(this, aIsDocument);
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetContentType(nsACString &aContentType)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetContentType(const nsACString &aContentType)
|
|
{
|
|
return NS_ERROR_FAILURE;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetContentCharset(nsACString &aContentCharset)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetContentCharset(const nsACString &aContentCharset)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetContentDisposition(uint32_t *aContentDisposition)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetContentDisposition(uint32_t aContentDisposition)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
|
|
{
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetContentLength(int64_t * aContentLength)
|
|
{
|
|
*aContentLength = -1;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsExtProtocolChannel::SetContentLength(int64_t aContentLength)
|
|
{
|
|
MOZ_ASSERT_UNREACHABLE("SetContentLength");
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetOwner(nsISupports * *aPrincipal)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetOwner(nsISupports * aPrincipal)
|
|
{
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetLoadInfo(nsILoadInfo **aLoadInfo)
|
|
{
|
|
NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetLoadInfo(nsILoadInfo *aLoadInfo)
|
|
{
|
|
mLoadInfo = aLoadInfo;
|
|
return NS_OK;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// From nsIRequest
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetName(nsACString &result)
|
|
{
|
|
return mUrl->GetSpec(result);
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::IsPending(bool *result)
|
|
{
|
|
*result = false;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::GetStatus(nsresult *status)
|
|
{
|
|
*status = mStatus;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::Cancel(nsresult status)
|
|
{
|
|
mStatus = status;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::Suspend()
|
|
{
|
|
MOZ_ASSERT_UNREACHABLE("Suspend");
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::Resume()
|
|
{
|
|
MOZ_ASSERT_UNREACHABLE("Resume");
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// From nsIChildChannel
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::ConnectParent(uint32_t registrarId)
|
|
{
|
|
mozilla::dom::ContentChild::GetSingleton()->
|
|
SendExtProtocolChannelConnectParent(registrarId);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::CompleteRedirectSetup(nsIStreamListener *listener,
|
|
nsISupports *context)
|
|
{
|
|
// For redirects to external protocols we AsyncOpen on the child
|
|
// (not the parent) because child channel has the right docshell
|
|
// (which is needed for the select dialog).
|
|
return AsyncOpen(listener, context);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// From nsIParentChannel (derives from nsIStreamListener)
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetParentListener(mozilla::net::HttpChannelParentListener* aListener)
|
|
{
|
|
// This is called as part of the connect parent operation from
|
|
// ContentParent::RecvExtProtocolChannelConnectParent. Setting
|
|
// this flag tells this channel to not proceed and makes AsyncOpen
|
|
// just no-op. Actual operation will happen from the child process
|
|
// via CompleteRedirectSetup call on the child channel.
|
|
mConnectedParent = true;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingProtectionDisabled()
|
|
{
|
|
// nothing to do
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::SetClassifierMatchedInfo(const nsACString& aList,
|
|
const nsACString& aProvider,
|
|
const nsACString& aFullHash)
|
|
{
|
|
// nothing to do
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::NotifyTrackingResource(bool aIsThirdParty)
|
|
{
|
|
// nothing to do
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::Delete()
|
|
{
|
|
// nothing to do
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::OnStartRequest(nsIRequest *aRequest,
|
|
nsISupports *aContext)
|
|
{
|
|
// no data is expected
|
|
MOZ_CRASH("No data expected from external protocol channel");
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::OnStopRequest(nsIRequest *aRequest,
|
|
nsISupports *aContext,
|
|
nsresult aStatusCode)
|
|
{
|
|
// no data is expected
|
|
MOZ_CRASH("No data expected from external protocol channel");
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExtProtocolChannel::OnDataAvailable(nsIRequest *aRequest,
|
|
nsISupports *aContext,
|
|
nsIInputStream *aInputStream,
|
|
uint64_t aOffset,
|
|
uint32_t aCount)
|
|
{
|
|
// no data is expected
|
|
MOZ_CRASH("No data expected from external protocol channel");
|
|
return NS_ERROR_UNEXPECTED;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// the default protocol handler implementation
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
nsExternalProtocolHandler::nsExternalProtocolHandler()
|
|
{
|
|
m_schemeName = "default";
|
|
}
|
|
|
|
|
|
nsExternalProtocolHandler::~nsExternalProtocolHandler()
|
|
{}
|
|
|
|
NS_IMPL_ADDREF(nsExternalProtocolHandler)
|
|
NS_IMPL_RELEASE(nsExternalProtocolHandler)
|
|
|
|
NS_INTERFACE_MAP_BEGIN(nsExternalProtocolHandler)
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIProtocolHandler)
|
|
NS_INTERFACE_MAP_ENTRY(nsIProtocolHandler)
|
|
NS_INTERFACE_MAP_ENTRY(nsIExternalProtocolHandler)
|
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMETHODIMP nsExternalProtocolHandler::GetScheme(nsACString &aScheme)
|
|
{
|
|
aScheme = m_schemeName;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExternalProtocolHandler::GetDefaultPort(int32_t *aDefaultPort)
|
|
{
|
|
*aDefaultPort = 0;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsExternalProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
|
|
{
|
|
// don't override anything.
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|
|
// returns TRUE if the OS can handle this protocol scheme and false otherwise.
|
|
bool nsExternalProtocolHandler::HaveExternalProtocolHandler(nsIURI * aURI)
|
|
{
|
|
MOZ_ASSERT(aURI);
|
|
nsAutoCString scheme;
|
|
aURI->GetScheme(scheme);
|
|
|
|
nsCOMPtr<nsIExternalProtocolService> extProtSvc(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
|
|
if (!extProtSvc) {
|
|
return false;
|
|
}
|
|
|
|
bool haveHandler = false;
|
|
extProtSvc->ExternalProtocolHandlerExists(scheme.get(), &haveHandler);
|
|
return haveHandler;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExternalProtocolHandler::GetProtocolFlags(uint32_t *aUritype)
|
|
{
|
|
// Make it norelative since it is a simple uri
|
|
*aUritype = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE |
|
|
URI_NON_PERSISTABLE | URI_DOES_NOT_RETURN_DATA;
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExternalProtocolHandler::NewURI(const nsACString &aSpec,
|
|
const char *aCharset, // ignore charset info
|
|
nsIURI *aBaseURI,
|
|
nsIURI **_retval)
|
|
{
|
|
return NS_MutateURI(NS_SIMPLEURIMUTATOR_CONTRACTID)
|
|
.SetSpec(aSpec)
|
|
.Finalize(_retval);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsExternalProtocolHandler::NewChannel2(nsIURI* aURI,
|
|
nsILoadInfo* aLoadInfo,
|
|
nsIChannel** aRetval)
|
|
{
|
|
NS_ENSURE_TRUE(aURI, NS_ERROR_UNKNOWN_PROTOCOL);
|
|
NS_ENSURE_TRUE(aRetval, NS_ERROR_UNKNOWN_PROTOCOL);
|
|
|
|
// Only try to return a channel if we have a protocol handler for the url.
|
|
// nsOSHelperAppService::LoadUriInternal relies on this to check trustedness
|
|
// for some platforms at least. (win uses ::ShellExecute and unix uses
|
|
// gnome_url_show.)
|
|
if (!HaveExternalProtocolHandler(aURI)) {
|
|
return NS_ERROR_UNKNOWN_PROTOCOL;
|
|
}
|
|
|
|
nsCOMPtr<nsIChannel> channel = new nsExtProtocolChannel(aURI, aLoadInfo);
|
|
channel.forget(aRetval);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsExternalProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **_retval)
|
|
{
|
|
return NewChannel2(aURI, nullptr, _retval);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// External protocol handler interface implementation
|
|
//////////////////////////////////////////////////////////////////////
|
|
NS_IMETHODIMP nsExternalProtocolHandler::ExternalAppExistsForScheme(const nsACString& aScheme, bool *_retval)
|
|
{
|
|
nsCOMPtr<nsIExternalProtocolService> extProtSvc(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
|
|
if (extProtSvc)
|
|
return extProtSvc->ExternalProtocolHandlerExists(
|
|
PromiseFlatCString(aScheme).get(), _retval);
|
|
|
|
// In case we don't have external protocol service.
|
|
*_retval = false;
|
|
return NS_OK;
|
|
}
|