Bug 1196151 - use BrowsingContext for external helper app handling of protocols, r=mattwoodrow

Differential Revision: https://phabricator.services.mozilla.com/D74434
This commit is contained in:
Gijs Kruitbosch 2020-05-11 13:13:03 +00:00
Родитель e83010ea13
Коммит 228e52aebe
30 изменённых файлов: 104 добавлений и 247 удалений

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

@ -11845,7 +11845,7 @@ nsresult nsDocShell::OnLinkClickSync(
nsresult rv =
extProtService->IsExposedProtocol(scheme.get(), &isExposed);
if (NS_SUCCEEDED(rv) && !isExposed) {
return extProtService->LoadURI(aURI, this);
return extProtService->LoadURI(aURI, mBrowsingContext);
}
}
}

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

@ -22,7 +22,6 @@ XPIDL_SOURCES += [
'nsIImageLoadingContent.idl',
'nsIMessageManager.idl',
'nsIObjectLoadingContent.idl',
'nsIRemoteWindowContext.idl',
'nsIScriptableContentIterator.idl',
'nsIScriptChannel.idl',
'nsISelectionController.idl',

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

@ -1,20 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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 "nsISupports.idl"
interface nsIURI;
[scriptable, builtinclass, uuid(94f4a92b-752e-4fd9-8345-11b069ca19f3)]
interface nsIRemoteWindowContext : nsISupports
{
/*
* Determines if the window is in private browsing.
*/
readonly attribute boolean usePrivateBrowsing;
void openURI(in nsIURI aURI);
};

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

@ -1411,30 +1411,6 @@ void ContentParent::Init() {
mScriptableHelper = new ScriptableCPInfo(this);
}
NS_IMPL_ISUPPORTS(RemoteWindowContext, nsIRemoteWindowContext,
nsIInterfaceRequestor)
RemoteWindowContext::RemoteWindowContext(BrowserParent* aBrowserParent)
: mBrowserParent(aBrowserParent) {}
NS_IMETHODIMP
RemoteWindowContext::GetInterface(const nsIID& aIID, void** aSink) {
return QueryInterface(aIID, aSink);
}
NS_IMETHODIMP
RemoteWindowContext::OpenURI(nsIURI* aURI) {
mBrowserParent->LoadURL(aURI);
return NS_OK;
}
NS_IMETHODIMP
RemoteWindowContext::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
nsCOMPtr<nsILoadContext> loadContext = mBrowserParent->GetLoadContext();
*aUsePrivateBrowsing = loadContext && loadContext->UsePrivateBrowsing();
return NS_OK;
}
void ContentParent::MaybeAsyncSendShutDownMessage() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!TryToRecycle());
@ -3750,7 +3726,11 @@ mozilla::ipc::IPCResult ContentParent::RecvAccumulateMixedContentHSTS(
}
mozilla::ipc::IPCResult ContentParent::RecvLoadURIExternal(
nsIURI* uri, PBrowserParent* windowContext) {
nsIURI* uri, const MaybeDiscarded<BrowsingContext>& aContext) {
if (aContext.IsNullOrDiscarded()) {
return IPC_OK();
}
nsCOMPtr<nsIExternalProtocolService> extProtService(
do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
if (!extProtService) {
@ -3761,9 +3741,8 @@ mozilla::ipc::IPCResult ContentParent::RecvLoadURIExternal(
return IPC_FAIL_NO_REASON(this);
}
RefPtr<RemoteWindowContext> context =
new RemoteWindowContext(static_cast<BrowserParent*>(windowContext));
extProtService->LoadURI(uri, context);
BrowsingContext* bc = aContext.get();
extProtService->LoadURI(uri, bc);
return IPC_OK();
}

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

@ -42,7 +42,6 @@
#include "nsIRemoteTab.h"
#include "nsIDOMGeoPositionCallback.h"
#include "nsIDOMGeoPositionErrorCallback.h"
#include "nsIRemoteWindowContext.h"
#include "nsRefPtrHashtable.h"
#include "PermissionMessageUtils.h"
#include "DriverCrashGuard.h"
@ -1017,8 +1016,8 @@ class ContentParent final
mozilla::ipc::IPCResult RecvNotificationEvent(
const nsString& aType, const NotificationEventData& aData);
mozilla::ipc::IPCResult RecvLoadURIExternal(nsIURI* uri,
PBrowserParent* windowContext);
mozilla::ipc::IPCResult RecvLoadURIExternal(
nsIURI* uri, const MaybeDiscarded<BrowsingContext>& aContext);
mozilla::ipc::IPCResult RecvExtProtocolChannelConnectParent(
const uint32_t& registrarId);
@ -1512,20 +1511,6 @@ bool IsWebRemoteType(const nsAString& aContentProcessType);
bool IsWebCoopCoepRemoteType(const nsAString& aContentProcessType);
class RemoteWindowContext final : public nsIRemoteWindowContext,
public nsIInterfaceRequestor {
public:
explicit RemoteWindowContext(BrowserParent* aBrowserParent);
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIREMOTEWINDOWCONTEXT
private:
~RemoteWindowContext() = default;
RefPtr<BrowserParent> mBrowserParent;
};
inline nsISupports* ToSupports(mozilla::dom::ContentParent* aContentParent) {
return static_cast<nsIContentParent*>(aContentParent);
}

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

@ -968,7 +968,7 @@ parent:
async StartVisitedQueries(nsIURI[] uri);
async SetURITitle(nsIURI uri, nsString title);
async LoadURIExternal(nsIURI uri, PBrowser windowContext);
async LoadURIExternal(nsIURI uri, MaybeDiscardedBrowsingContext browsingContext);
async ExtProtocolChannelConnectParent(uint32_t registrarId);
// PrefService message

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

@ -12,6 +12,7 @@ interface nsIHandlerApp;
interface nsIArray;
interface nsIMutableArray;
interface nsIInterfaceRequestor;
webidl BrowsingContext;
typedef long nsHandlerInfoAction;
@ -78,7 +79,7 @@ interface nsIHandlerInfo : nsISupports {
* @param aURI
* The URI to launch this application with
*
* @param aWindowContext
* @param aBrowsingContext
* The window to parent the dialog against, and, if a web handler
* is chosen, it is loaded in this window as well. See
* nsIHandlerApp.launchWithURI for more details.
@ -87,7 +88,7 @@ interface nsIHandlerInfo : nsISupports {
* call. Other exceptions may be thrown.
*/
void launchWithURI(in nsIURI aURI,
[optional] in nsIInterfaceRequestor aWindowContext);
[optional] in BrowsingContext aBrowsingContext);
/**
* preferredAction is how the user specified they would like to handle
@ -247,10 +248,9 @@ interface nsIHandlerApp : nsISupports {
* @param aURI
* The URI to launch this application with
*
* @param aWindowContext
* @param aBrowsingContext
*
* Currently only relevant to web-handler apps. If given, this
* represents the docshell to load the handler in and is passed
* This represents the docshell to load the handler in and is passed
* through to nsIURILoader.openURI. If this parameter is null or
* not present, the web handler app implementation will attempt to
* find/create a place to load the handler and do so. As of this
@ -260,7 +260,7 @@ interface nsIHandlerApp : nsISupports {
* off to the system default browser (bug 394479).
*/
void launchWithURI(in nsIURI aURI,
[optional] in nsIInterfaceRequestor aWindowContext);
[optional] in BrowsingContext aBrowsingContext);
};

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

@ -44,8 +44,7 @@ ParentChannelListener::ParentChannelListener(
mShouldIntercept(false),
mShouldSuspendIntercept(false),
mInterceptCanceled(false),
mBrowsingContext(aBrowsingContext),
mUsePrivateBrowsing(aUsePrivateBrowsing) {
mBrowsingContext(aBrowsingContext) {
LOG(("ParentChannelListener::ParentChannelListener [this=%p, next=%p]", this,
aListener));
@ -72,7 +71,6 @@ NS_INTERFACE_MAP_BEGIN(ParentChannelListener)
NS_INTERFACE_MAP_ENTRY(nsINetworkInterceptController)
NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAuthPromptProvider, mBrowsingContext)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIRemoteWindowContext, mBrowsingContext)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY_CONCRETE(ParentChannelListener)
NS_INTERFACE_MAP_END
@ -158,8 +156,7 @@ ParentChannelListener::OnAfterLastPart(nsresult aStatus) {
NS_IMETHODIMP
ParentChannelListener::GetInterface(const nsIID& aIID, void** result) {
if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController)) ||
aIID.Equals(NS_GET_IID(nsIRemoteWindowContext))) {
if (aIID.Equals(NS_GET_IID(nsINetworkInterceptController))) {
return QueryInterface(aIID, result);
}
@ -421,38 +418,6 @@ ParentChannelListener::GetAuthPrompt(uint32_t aPromptReason, const nsIID& iid,
return NS_OK;
}
//-----------------------------------------------------------------------------
// ParentChannelListener::nsIRemoteWindowContext
//
NS_IMETHODIMP
ParentChannelListener::OpenURI(nsIURI* aURI) {
nsCString spec;
aURI->GetSpec(spec);
RefPtr<dom::CanonicalBrowsingContext> bc = mBrowsingContext;
NS_DispatchToMainThread(
NS_NewRunnableFunction("ParentChannelListener::OpenURI", [spec, bc]() {
dom::LoadURIOptions loadURIOptions;
loadURIOptions.mTriggeringPrincipal =
nsContentUtils::GetSystemPrincipal();
loadURIOptions.mLoadFlags =
nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
ErrorResult rv;
bc->LoadURI(NS_ConvertUTF8toUTF16(spec), loadURIOptions, rv);
}));
return NS_OK;
}
NS_IMETHODIMP
ParentChannelListener::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing) {
*aUsePrivateBrowsing = mUsePrivateBrowsing;
return NS_OK;
}
//-----------------------------------------------------------------------------
// ParentChannelListener::nsIThreadRetargetableStreamListener
//

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

@ -13,7 +13,6 @@
#include "nsIInterfaceRequestor.h"
#include "nsIMultiPartChannel.h"
#include "nsINetworkInterceptController.h"
#include "nsIRemoteWindowContext.h"
#include "nsIStreamListener.h"
#include "nsIThreadRetargetableStreamListener.h"
@ -36,8 +35,7 @@ class ParentChannelListener final : public nsIInterfaceRequestor,
public nsIMultiPartChannelListener,
public nsINetworkInterceptController,
public nsIThreadRetargetableStreamListener,
private nsIAuthPromptProvider,
private nsIRemoteWindowContext {
private nsIAuthPromptProvider {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEREQUESTOR
@ -46,7 +44,6 @@ class ParentChannelListener final : public nsIInterfaceRequestor,
NS_DECL_NSIMULTIPARTCHANNELLISTENER
NS_DECL_NSINETWORKINTERCEPTCONTROLLER
NS_DECL_NSIAUTHPROMPTPROVIDER
NS_DECL_NSIREMOTEWINDOWCONTEXT
NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
NS_DECLARE_STATIC_IID_ACCESSOR(PARENT_CHANNEL_LISTENER)
@ -109,9 +106,6 @@ class ParentChannelListener final : public nsIInterfaceRequestor,
// True if we received OnStartRequest for a nsIMultiPartChannel, and are
// expected AllPartsStopped to be called when complete.
bool mIsMultiPart = false;
// True if the nsILoadContext for this channel has private browsing enabled.
bool mUsePrivateBrowsing = false;
};
NS_DEFINE_STATIC_IID_ACCESSOR(ParentChannelListener, PARENT_CHANNEL_LISTENER)

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

@ -79,7 +79,7 @@ var dialog = {
_URI: null,
_itemChoose: null,
_okButton: null,
_windowCtxt: null,
_browsingContext: null,
_buttonDisabled: true,
// Methods
@ -90,25 +90,10 @@ var dialog = {
initialize: function initialize() {
this._handlerInfo = window.arguments[7].QueryInterface(Ci.nsIHandlerInfo);
this._URI = window.arguments[8].QueryInterface(Ci.nsIURI);
this._windowCtxt = window.arguments[9];
this._browsingContext = window.arguments[9];
let usePrivateBrowsing = false;
if (this._windowCtxt) {
// The context should be nsIRemoteWindowContext in OOP, or nsIDOMWindow otherwise.
try {
usePrivateBrowsing = this._windowCtxt.getInterface(
Ci.nsIRemoteWindowContext
).usePrivateBrowsing;
} catch (e) {
try {
let opener = this._windowCtxt.getInterface(Ci.nsIDOMWindow);
usePrivateBrowsing = PrivateBrowsingUtils.isContentWindowPrivate(
opener
);
} catch (e) {
Cu.reportError(`No interface to determine privateness: ${e}`);
}
}
this._windowCtxt.QueryInterface(Ci.nsIInterfaceRequestor);
if (this._browsingContext) {
usePrivateBrowsing = this._browsingContext.usePrivateBrowsing;
}
this.isPrivate =
@ -348,7 +333,7 @@ var dialog = {
);
hs.store(this._handlerInfo);
this._handlerInfo.launchWithURI(this._URI, this._windowCtxt);
this._handlerInfo.launchWithURI(this._URI, this._browsingContext);
window.close();
},

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

@ -82,8 +82,8 @@ nsFlatpakHandlerApp::Equals(nsIHandlerApp* aHandlerApp, bool* _retval) {
}
NS_IMETHODIMP
nsFlatpakHandlerApp::LaunchWithURI(nsIURI* aUri,
nsIInterfaceRequestor* aRequestor) {
nsFlatpakHandlerApp::LaunchWithURI(
nsIURI* aUri, mozilla::dom::BrowsingContext* aBrowsingContext) {
nsCString spec;
aUri->GetSpec(spec);
GError* error = nullptr;
@ -229,7 +229,8 @@ nsGIOMimeApp::Equals(nsIHandlerApp* aHandlerApp, bool* _retval) {
}
NS_IMETHODIMP
nsGIOMimeApp::LaunchWithURI(nsIURI* aUri, nsIInterfaceRequestor* aRequestor) {
nsGIOMimeApp::LaunchWithURI(nsIURI* aUri,
mozilla::dom::BrowsingContext* aBrowsingContext) {
GList uris = {0};
nsCString spec;
aUri->GetSpec(spec);

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

@ -117,7 +117,7 @@ NS_IMETHODIMP RemoteHandlerApp::Equals(nsIHandlerApp* aHandlerApp,
}
NS_IMETHODIMP RemoteHandlerApp::LaunchWithURI(
nsIURI* aURI, nsIInterfaceRequestor* aWindowContext) {
nsIURI* aURI, BrowsingContext* aBrowsingContext) {
return NS_ERROR_NOT_IMPLEMENTED;
}

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

@ -105,9 +105,9 @@ NS_IMETHODIMP ProxyHandlerInfo::GetDefaultDescription(
}
/* void launchWithURI (in nsIURI aURI,
[optional] in nsIInterfaceRequestor aWindowContext); */
[optional] in BrowsingContext aBrowsingContext); */
NS_IMETHODIMP ProxyHandlerInfo::LaunchWithURI(
nsIURI* aURI, nsIInterfaceRequestor* aWindowContext) {
nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) {
return NS_ERROR_NOT_IMPLEMENTED;
}

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

@ -2,7 +2,6 @@
* 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/. */
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.defineModuleGetter(
@ -60,7 +59,7 @@ nsWebHandlerApp.prototype = {
return false;
},
launchWithURI(aURI, aWindowContext) {
launchWithURI(aURI, aBrowsingContext) {
// XXX need to strip passwd & username from URI to handle, as per the
// WhatWG HTML5 draft. nsSimpleURL, which is what we're going to get,
// can't do this directly. Ideally, we'd fix nsStandardURL to make it
@ -76,67 +75,18 @@ nsWebHandlerApp.prototype = {
let policy = WebExtensionPolicy.getByURI(uriToSend);
let privateAllowed = !policy || policy.privateBrowsingAllowed;
// if we have a window context, use the URI loader to load there
if (aWindowContext) {
try {
let remoteWindow = aWindowContext.getInterface(
Ci.nsIRemoteWindowContext
// if we have a context, use the URI loader to load there
if (aBrowsingContext) {
if (aBrowsingContext.usePrivateBrowsing && !privateAllowed) {
throw Components.Exception(
"Extension not allowed in private windows.",
Cr.NS_ERROR_FILE_NOT_FOUND
);
if (remoteWindow.usePrivateBrowsing && !privateAllowed) {
throw Components.Exception(
"Extension not allowed in private windows.",
Cr.NS_ERROR_FILE_NOT_FOUND
);
}
// getInterface throws if the object doesn't implement the given
// interface, so this try/catch statement is more of an if.
// If aWindowContext refers to a remote docshell, send the load
// request to the correct process.
remoteWindow.openURI(uriToSend);
return;
} catch (e) {
if (e.result != Cr.NS_NOINTERFACE) {
throw e;
}
}
try {
let isPrivate = aWindowContext
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing;
if (isPrivate && !privateAllowed) {
throw Components.Exception(
"Extension not allowed in private windows.",
Cr.NS_ERROR_FILE_NOT_FOUND
);
}
} catch (e) {
if (e.result != Cr.NS_NOINTERFACE) {
throw e;
}
}
// create a channel from this URI
var channel = NetUtil.newChannel({
uri: uriToSend,
loadUsingSystemPrincipal: true,
});
channel.loadFlags = Ci.nsIChannel.LOAD_DOCUMENT_URI;
// load the channel
var uriLoader = Cc["@mozilla.org/uriloader;1"].getService(
Ci.nsIURILoader
);
// XXX ideally, whether to pass the IS_CONTENT_PREFERRED flag should be
// passed in from above. Practically, the flag is probably a reasonable
// default since browsers don't care much, and link click is likely to be
// the more interesting case for non-browser apps. See
// <https://bugzilla.mozilla.org/show_bug.cgi?id=392957#c9> for details.
uriLoader.openURI(
channel,
Ci.nsIURILoader.IS_CONTENT_PREFERRED,
aWindowContext
let triggeringPrincipal = Services.scriptSecurityManager.getSystemPrincipal();
Services.tm.dispatchToMainThread(() =>
aBrowsingContext.loadURI(uriSpecToSend, { triggeringPrincipal })
);
return;
}
@ -144,7 +94,7 @@ nsWebHandlerApp.prototype = {
let win = Services.wm.getMostRecentWindow("navigator:browser");
// If this is an extension handler, check private browsing access.
if (!privateAllowed && PrivateBrowsingUtils.isContentWindowPrivate(win)) {
if (!privateAllowed && PrivateBrowsingUtils.isWindowPrivate(win)) {
throw Components.Exception(
"Extension not allowed in private windows.",
Cr.NS_ERROR_FILE_NOT_FOUND

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

@ -67,8 +67,8 @@ nsAndroidHandlerApp::Equals(nsIHandlerApp* aHandlerApp, bool* aRetval) {
}
NS_IMETHODIMP
nsAndroidHandlerApp::LaunchWithURI(nsIURI* aURI,
nsIInterfaceRequestor* aWindowContext) {
nsAndroidHandlerApp::LaunchWithURI(
nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) {
nsCString uriSpec;
aURI->GetSpec(uriSpec);
return java::GeckoAppShell::OpenUriExternal(uriSpec, mMimeType, mPackageName,

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

@ -202,8 +202,9 @@ nsMIMEInfoAndroid::GetDefaultDescription(nsAString& aDesc) {
}
NS_IMETHODIMP
nsMIMEInfoAndroid::LaunchWithURI(nsIURI* aURI, nsIInterfaceRequestor* req) {
return mPrefApp->LaunchWithURI(aURI, req);
nsMIMEInfoAndroid::LaunchWithURI(
nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) {
return mPrefApp->LaunchWithURI(aURI, aBrowsingContext);
}
NS_IMETHODIMP
@ -408,6 +409,6 @@ nsresult nsMIMEInfoAndroid::SystemChooser::Equals(nsIHandlerApp* aHandlerApp,
}
nsresult nsMIMEInfoAndroid::SystemChooser::LaunchWithURI(
nsIURI* aURI, nsIInterfaceRequestor*) {
nsIURI* aURI, mozilla::dom::BrowsingContext*) {
return mOuter->LoadUriInternal(aURI);
}

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

@ -18,8 +18,8 @@ class nsLocalHandlerAppMac : public nsLocalHandlerApp {
: nsLocalHandlerApp(aName, aExecutable) {}
virtual ~nsLocalHandlerAppMac() {}
NS_IMETHOD LaunchWithURI(nsIURI* aURI,
nsIInterfaceRequestor* aWindowContext) override;
NS_IMETHOD LaunchWithURI(
nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) override;
NS_IMETHOD GetName(nsAString& aName) override;
};

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

@ -30,7 +30,7 @@ NS_IMETHODIMP nsLocalHandlerAppMac::GetName(nsAString& aName) {
* somewhere more central (see bug 389922).
*/
NS_IMETHODIMP
nsLocalHandlerAppMac::LaunchWithURI(nsIURI* aURI, nsIInterfaceRequestor* aWindowContext) {
nsLocalHandlerAppMac::LaunchWithURI(nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
nsresult rv;

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

@ -77,8 +77,8 @@ nsDBusHandlerApp::Equals(nsIHandlerApp* aHandlerApp, bool* _retval) {
}
NS_IMETHODIMP
nsDBusHandlerApp::LaunchWithURI(nsIURI* aURI,
nsIInterfaceRequestor* aWindowContext) {
nsDBusHandlerApp::LaunchWithURI(
nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) {
nsAutoCString spec;
nsresult rv = aURI->GetAsciiSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);

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

@ -921,13 +921,13 @@ static const char kExternalProtocolDefaultPref[] =
NS_IMETHODIMP
nsExternalHelperAppService::LoadURI(nsIURI* aURI,
nsIInterfaceRequestor* aWindowContext) {
BrowsingContext* aBrowsingContext) {
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_ARG_POINTER(aBrowsingContext);
if (XRE_IsContentProcess()) {
nsCOMPtr<nsIBrowserChild> browserChild(do_GetInterface(aWindowContext));
mozilla::dom::ContentChild::GetSingleton()->SendLoadURIExternal(
aURI, static_cast<dom::BrowserChild*>(browserChild.get()));
aURI, aBrowsingContext);
return NS_OK;
}
@ -977,7 +977,7 @@ nsExternalHelperAppService::LoadURI(nsIURI* aURI,
// a helper app or the system default, we just launch the URI.
if (!alwaysAsk && (preferredAction == nsIHandlerInfo::useHelperApp ||
preferredAction == nsIHandlerInfo::useSystemDefault)) {
rv = handler->LaunchWithURI(uri, aWindowContext);
rv = handler->LaunchWithURI(uri, aBrowsingContext);
// We are not supposed to ask, but when file not found the user most likely
// uninstalled the application which handles the uri so we will continue
// by application chooser dialog.
@ -990,7 +990,7 @@ nsExternalHelperAppService::LoadURI(nsIURI* aURI,
do_CreateInstance("@mozilla.org/content-dispatch-chooser;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
return chooser->Ask(handler, aWindowContext, uri,
return chooser->Ask(handler, aBrowsingContext, uri,
nsIContentDispatchChooser::REASON_CANNOT_HANDLE);
}

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

@ -74,7 +74,7 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService,
NS_IMETHOD GetProtocolHandlerInfo(const nsACString& aScheme,
nsIHandlerInfo** aHandlerInfo) override;
NS_IMETHOD LoadURI(nsIURI* aURI,
nsIInterfaceRequestor* aWindowContext) override;
mozilla::dom::BrowsingContext* aBrowsingContext) override;
NS_IMETHOD SetProtocolHandlerDefaults(nsIHandlerInfo* aHandlerInfo,
bool aOSHandlerExists) override;

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

@ -158,14 +158,12 @@ nsresult nsExtProtocolChannel::OpenURL() {
"the protocol?");
#endif
nsCOMPtr<nsIInterfaceRequestor> aggCallbacks;
rv = NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
getter_AddRefs(aggCallbacks));
RefPtr<mozilla::dom::BrowsingContext> ctx;
rv = mLoadInfo->GetTargetBrowsingContext(getter_AddRefs(ctx));
if (NS_FAILED(rv)) {
goto finish;
}
rv = extProtService->LoadURI(mUrl, aggCallbacks);
rv = extProtService->LoadURI(mUrl, ctx);
if (NS_SUCCEEDED(rv) && mListener) {
mStatus = NS_ERROR_NO_CONTENT;

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

@ -8,6 +8,7 @@ interface nsIHandlerInfo;
interface nsIHelperAppLauncher;
interface nsIURI;
interface nsIInterfaceRequestor;
webidl BrowsingContext;
/**
* This is used to ask a user what they would like to do with a given piece of
@ -27,18 +28,15 @@ interface nsIContentDispatchChooser : nsISupports {
* @param aHander
* The interface describing the details of how this content should or
* can be handled.
* @param aWindowContext
* The parent window context to show this chooser. This can be null,
* and some implementations may not care about it. Generally, you'll
* want to pass an nsIDOMWindow in so the chooser can be properly
* parented when opened.
* @param aBrowsingContext
* The browsing context that's the parent for this chooser.
* @param aURI
* The URI of the resource that we are asking about.
* @param aReason
* The reason why we are asking (see above).
*/
void ask(in nsIHandlerInfo aHandler,
in nsIInterfaceRequestor aWindowContext,
in BrowsingContext aBrowsingContext,
in nsIURI aURI,
in unsigned long aReason);
};

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

@ -35,8 +35,7 @@ interface nsIExternalHelperAppService : nsISupports
* @param aMimeContentType The content type of the incoming data
* @param aRequest The request corresponding to the incoming data
* @param aContentContext Used in processing content document refresh
* headers after target content is downloaded. Note in e10s land
* this is likely a CPOW that points to a window in the child process.
* headers after target content is downloaded.
* @param aForceSave True to always save this content to disk, regardless of
* nsIMIMEInfo and other such influences.
* @param aWindowContext Used in parenting helper app dialogs, usually

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

@ -11,6 +11,8 @@ interface nsIFile;
interface nsIInterfaceRequestor;
interface nsIHandlerInfo;
webidl BrowsingContext;
/**
* The external protocol service is used for finding and launching
* web handlers (a la registerProtocolHandler in the HTML5 draft) or
@ -95,8 +97,8 @@ interface nsIExternalProtocolService : nsISupports
* @param aURI
* The URI to load
*
* @param aWindowContext
* The window to parent the dialog against, and, if a web handler
* @param aBrowsingContext
* The context to parent the dialog against, and, if a web handler
* is chosen, it is loaded in this window as well. This parameter
* may be ultimately passed nsIURILoader.openURI in the case of a
* web handler, and aWindowContext is null or not present, web
@ -108,7 +110,7 @@ interface nsIExternalProtocolService : nsISupports
* (bug 394479).
*/
void loadURI(in nsIURI aURI,
[optional] in nsIInterfaceRequestor aWindowContext);
in BrowsingContext aBrowsingContext);
/**
* Gets a human-readable description for the application responsible for

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

@ -89,8 +89,8 @@ nsLocalHandlerApp::Equals(nsIHandlerApp* aHandlerApp, bool* _retval) {
}
NS_IMETHODIMP
nsLocalHandlerApp::LaunchWithURI(nsIURI* aURI,
nsIInterfaceRequestor* aWindowContext) {
nsLocalHandlerApp::LaunchWithURI(
nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) {
// pass the entire URI to the handler.
nsAutoCString spec;
aURI->GetAsciiSpec(spec);

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

@ -307,8 +307,7 @@ nsMIMEInfoBase::LaunchWithFile(nsIFile* aFile) {
}
NS_IMETHODIMP
nsMIMEInfoBase::LaunchWithURI(nsIURI* aURI,
nsIInterfaceRequestor* aWindowContext) {
nsMIMEInfoBase::LaunchWithURI(nsIURI* aURI, BrowsingContext* aBrowsingContext) {
// This is only being called with protocol handlers
NS_ASSERTION(mClass == eProtocolInfo,
"nsMIMEInfoBase should be a protocol handler");
@ -353,7 +352,7 @@ nsMIMEInfoBase::LaunchWithURI(nsIURI* aURI,
return NS_ERROR_FILE_NOT_FOUND;
}
}
return mPreferredApplication->LaunchWithURI(aURI, aWindowContext);
return mPreferredApplication->LaunchWithURI(aURI, aBrowsingContext);
}
return NS_ERROR_INVALID_ARG;

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

@ -15,6 +15,7 @@
#include "nsCOMPtr.h"
#include "nsIURI.h"
#include "nsIProcess.h"
#include "mozilla/dom/BrowsingContext.h"
/**
* UTF8 moz-icon URI string for the default handler application's icon, if
@ -57,8 +58,8 @@ class nsMIMEInfoBase : public nsIMIMEInfo {
nsIMutableArray** aPossibleAppHandlers) override;
NS_IMETHOD GetDefaultDescription(nsAString& aDefaultDescription) override;
NS_IMETHOD LaunchWithFile(nsIFile* aFile) override;
NS_IMETHOD LaunchWithURI(nsIURI* aURI,
nsIInterfaceRequestor* aWindowContext) override;
NS_IMETHOD LaunchWithURI(
nsIURI* aURI, mozilla::dom::BrowsingContext* aBrowsingContext) override;
NS_IMETHOD GetPreferredAction(nsHandlerInfoAction* aPreferredAction) override;
NS_IMETHOD SetPreferredAction(nsHandlerInfoAction aPreferredAction) override;
NS_IMETHOD GetAlwaysAskBeforeHandling(

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

@ -45,11 +45,32 @@ add_task(async function() {
);
handlerSvc.store(protoInfo);
// Middle-click a testprotocol link and check the new tab is correct
let link = "#link";
const expectedURL =
"https://example.com/foobar?uri=web%2Btestprotocol%3Atest";
// Create a framed link:
await SpecialPowers.spawn(browser, [], async function() {
let iframe = content.document.createElement("iframe");
iframe.src = `data:text/html,<a href="web+testprotocol:test">Click me</a>`;
content.document.body.append(iframe);
// Can't return this promise because it resolves to the event object.
await ContentTaskUtils.waitForEvent(iframe, "load");
iframe.contentDocument.querySelector("a").click();
});
let kidContext = browser.browsingContext.children[0];
await TestUtils.waitForCondition(() => {
let spec = kidContext.currentWindowGlobal?.documentURI?.spec || "";
return spec == expectedURL;
});
is(
kidContext.currentWindowGlobal.documentURI.spec,
expectedURL,
"Should load in frame."
);
// Middle-click a testprotocol link and check the new tab is correct
let link = "#link";
let promiseTabOpened = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL);
await BrowserTestUtils.synthesizeMouseAtCenter(link, { button: 1 }, browser);
let tab = await promiseTabOpened;

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

@ -21,7 +21,7 @@ class nsLocalHandlerAppUIKit final : public nsLocalHandlerApp {
: nsLocalHandlerApp(aName, aExecutable) {}
NS_IMETHOD LaunchWithURI(nsIURI* aURI,
nsIInterfaceRequestor* aWindowContext) override;
BrowsingContext* aBrowsingContext) override;
};
#endif /* nslocalhandlerappuikit_h_ */