Bug 1705211, r=nika,ckerschb

Differential Revision: https://phabricator.services.mozilla.com/D131856
This commit is contained in:
Gijs Kruitbosch
2021-12-01 12:36:07 +00:00
parent d8a40645d2
commit fd9be387e5
9 changed files with 40 additions and 12 deletions

View File

@@ -12765,7 +12765,7 @@ nsresult nsDocShell::OnLinkClickSync(nsIContent* aContent,
extProtService->IsExposedProtocol(scheme.get(), &isExposed); extProtService->IsExposedProtocol(scheme.get(), &isExposed);
if (NS_SUCCEEDED(rv) && !isExposed) { if (NS_SUCCEEDED(rv) && !isExposed) {
return extProtService->LoadURI(aLoadState->URI(), triggeringPrincipal, return extProtService->LoadURI(aLoadState->URI(), triggeringPrincipal,
mBrowsingContext, nullptr, mBrowsingContext,
/* aTriggeredExternally */ false); /* aTriggeredExternally */ false);
} }
} }

View File

@@ -4448,6 +4448,7 @@ mozilla::ipc::IPCResult ContentParent::RecvAccumulateMixedContentHSTS(
mozilla::ipc::IPCResult ContentParent::RecvLoadURIExternal( mozilla::ipc::IPCResult ContentParent::RecvLoadURIExternal(
nsIURI* uri, nsIPrincipal* aTriggeringPrincipal, nsIURI* uri, nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aRedirectPrincipal,
const MaybeDiscarded<BrowsingContext>& aContext, const MaybeDiscarded<BrowsingContext>& aContext,
bool aWasExternallyTriggered) { bool aWasExternallyTriggered) {
if (aContext.IsDiscarded()) { if (aContext.IsDiscarded()) {
@@ -4465,7 +4466,7 @@ mozilla::ipc::IPCResult ContentParent::RecvLoadURIExternal(
} }
BrowsingContext* bc = aContext.get(); BrowsingContext* bc = aContext.get();
extProtService->LoadURI(uri, aTriggeringPrincipal, bc, extProtService->LoadURI(uri, aTriggeringPrincipal, aRedirectPrincipal, bc,
aWasExternallyTriggered); aWasExternallyTriggered);
return IPC_OK(); return IPC_OK();
} }

View File

@@ -1062,6 +1062,7 @@ class ContentParent final
mozilla::ipc::IPCResult RecvLoadURIExternal( mozilla::ipc::IPCResult RecvLoadURIExternal(
nsIURI* uri, nsIPrincipal* triggeringPrincipal, nsIURI* uri, nsIPrincipal* triggeringPrincipal,
nsIPrincipal* redirectPrincipal,
const MaybeDiscarded<BrowsingContext>& aContext, const MaybeDiscarded<BrowsingContext>& aContext,
bool aWasExternallyTriggered); bool aWasExternallyTriggered);
mozilla::ipc::IPCResult RecvExtProtocolChannelConnectParent( mozilla::ipc::IPCResult RecvExtProtocolChannelConnectParent(

View File

@@ -1076,6 +1076,7 @@ parent:
async LoadURIExternal(nsIURI uri, async LoadURIExternal(nsIURI uri,
nsIPrincipal triggeringPrincipal, nsIPrincipal triggeringPrincipal,
nsIPrincipal redirectPrincipal,
MaybeDiscardedBrowsingContext browsingContext, MaybeDiscardedBrowsingContext browsingContext,
bool wasExternallyTriggered); bool wasExternallyTriggered);
async ExtProtocolChannelConnectParent(uint64_t registrarId); async ExtProtocolChannelConnectParent(uint64_t registrarId);

View File

@@ -1061,13 +1061,15 @@ nsresult nsExternalHelperAppService::EscapeURI(nsIURI* aURI, nsIURI** aResult) {
NS_IMETHODIMP NS_IMETHODIMP
nsExternalHelperAppService::LoadURI(nsIURI* aURI, nsExternalHelperAppService::LoadURI(nsIURI* aURI,
nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aRedirectPrincipal,
BrowsingContext* aBrowsingContext, BrowsingContext* aBrowsingContext,
bool aTriggeredExternally) { bool aTriggeredExternally) {
NS_ENSURE_ARG_POINTER(aURI); NS_ENSURE_ARG_POINTER(aURI);
if (XRE_IsContentProcess()) { if (XRE_IsContentProcess()) {
mozilla::dom::ContentChild::GetSingleton()->SendLoadURIExternal( mozilla::dom::ContentChild::GetSingleton()->SendLoadURIExternal(
aURI, aTriggeringPrincipal, aBrowsingContext, aTriggeredExternally); aURI, aTriggeringPrincipal, aRedirectPrincipal, aBrowsingContext,
aTriggeredExternally);
return NS_OK; return NS_OK;
} }
@@ -1159,8 +1161,10 @@ nsExternalHelperAppService::LoadURI(nsIURI* aURI,
do_CreateInstance("@mozilla.org/content-dispatch-chooser;1", &rv); do_CreateInstance("@mozilla.org/content-dispatch-chooser;1", &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
return chooser->HandleURI(handler, escapedURI, aTriggeringPrincipal, return chooser->HandleURI(
aBrowsingContext, aTriggeredExternally); handler, escapedURI,
aRedirectPrincipal ? aRedirectPrincipal : aTriggeringPrincipal,
aBrowsingContext, aTriggeredExternally);
} }
////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -85,6 +85,7 @@ class nsExternalHelperAppService : public nsIExternalHelperAppService,
nsIHandlerInfo** aHandlerInfo) override; nsIHandlerInfo** aHandlerInfo) override;
NS_IMETHOD LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal, NS_IMETHOD LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal,
nsIPrincipal* aRedirectPrincipal,
mozilla::dom::BrowsingContext* aBrowsingContext, mozilla::dom::BrowsingContext* aBrowsingContext,
bool aWasTriggeredExternally) override; bool aWasTriggeredExternally) override;
NS_IMETHOD SetProtocolHandlerDefaults(nsIHandlerInfo* aHandlerInfo, NS_IMETHOD SetProtocolHandlerDefaults(nsIHandlerInfo* aHandlerInfo,

View File

@@ -164,9 +164,15 @@ nsresult nsExtProtocolChannel::OpenURL() {
goto finish; goto finish;
} }
RefPtr<nsIPrincipal> principal = mLoadInfo->TriggeringPrincipal(); RefPtr<nsIPrincipal> triggeringPrincipal = mLoadInfo->TriggeringPrincipal();
rv = extProtService->LoadURI(mUrl, principal, ctx, RefPtr<nsIPrincipal> redirectPrincipal;
mLoadInfo->GetLoadTriggeredFromExternal()); if (!mLoadInfo->RedirectChain().IsEmpty()) {
mLoadInfo->RedirectChain().LastElement()->GetPrincipal(
getter_AddRefs(redirectPrincipal));
}
rv =
extProtService->LoadURI(mUrl, triggeringPrincipal, redirectPrincipal,
ctx, mLoadInfo->GetLoadTriggeredFromExternal());
if (NS_SUCCEEDED(rv) && mListener) { if (NS_SUCCEEDED(rv) && mListener) {
mStatus = NS_ERROR_NO_CONTENT; mStatus = NS_ERROR_NO_CONTENT;

View File

@@ -101,6 +101,11 @@ interface nsIExternalProtocolService : nsISupports
* @param aTriggeringPrincipal * @param aTriggeringPrincipal
* The principal triggering this load. * The principal triggering this load.
* *
* @param aRedirectPrincipal
* The last post-redirect principal triggering this load.
* Used for display and permission purposes. If null, we'll
* use the triggering principal.
*
* @param aBrowsingContext * @param aBrowsingContext
* The context to parent the dialog against, and, if a web handler * The context to parent the dialog against, and, if a web handler
* is chosen, it is loaded in this window as well. This parameter * is chosen, it is loaded in this window as well. This parameter
@@ -118,6 +123,7 @@ interface nsIExternalProtocolService : nsISupports
*/ */
void loadURI(in nsIURI aURI, void loadURI(in nsIURI aURI,
[optional] in nsIPrincipal aTriggeringPrincipal, [optional] in nsIPrincipal aTriggeringPrincipal,
[optional] in nsIPrincipal aRedirectPrincipal,
[optional] in BrowsingContext aBrowsingContext, [optional] in BrowsingContext aBrowsingContext,
[optional] in bool aWasTriggeredExternally); [optional] in bool aWasTriggeredExternally);

View File

@@ -9,7 +9,7 @@ let gHandlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(
const TEST_PATH = getRootDirectory(gTestPath).replace( const TEST_PATH = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content", "chrome://mochitests/content",
"http://example.com" "https://example.com"
); );
/** /**
@@ -176,15 +176,23 @@ add_task(async function test_web_app_doesnt_ask() {
}); });
add_task(async function external_https_redirect_doesnt_ask() { add_task(async function external_https_redirect_doesnt_ask() {
Services.perms.addFromPrincipal(
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
"https://example.com"
),
"open-protocol-handler^local-app-test",
Services.perms.ALLOW_ACTION
);
// Listen for a dialog open and fail the test if it does: // Listen for a dialog open and fail the test if it does:
let dialogOpenListener = () => ok(false, "Shouldn't have opened a dialog!"); let dialogOpenListener = () => ok(false, "Shouldn't have opened a dialog!");
document.documentElement.addEventListener("dialogopen", dialogOpenListener); document.documentElement.addEventListener("dialogopen", dialogOpenListener);
registerCleanupFunction(() => registerCleanupFunction(() => {
document.documentElement.removeEventListener( document.documentElement.removeEventListener(
"dialogopen", "dialogopen",
dialogOpenListener dialogOpenListener
) );
); Services.perms.removeAll();
});
let initialTab = gBrowser.selectedTab; let initialTab = gBrowser.selectedTab;